15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/suggestions/suggestions_service.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <sstream> 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <string> 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/histogram.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/sparse_histogram.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h" 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/time/time.h" 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h" 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/suggestions/blacklist_store.h" 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/suggestions/suggestions_store.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/variations/variations_associated_data.h" 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/variations/variations_http_header_provider.h" 2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/base/escape.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/load_flags.h" 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/net_errors.h" 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/url_util.h" 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_response_headers.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_status_code.h" 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_util.h" 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_status.h" 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "url/gurl.h" 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using base::CancelableClosure; 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace suggestions { 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Used to UMA log the state of the last response from the server. 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)enum SuggestionsResponseState { 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RESPONSE_EMPTY, 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RESPONSE_INVALID, 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RESPONSE_VALID, 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RESPONSE_STATE_SIZE 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Will log the supplied response |state|. 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void LogResponseState(SuggestionsResponseState state) { 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Suggestions.ResponseState", state, 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RESPONSE_STATE_SIZE); 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Obtains the experiment parameter under the supplied |key|, or empty string 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// if the parameter does not exist. 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string GetExperimentParam(const std::string& key) { 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return variations::GetVariationParamValue(kSuggestionsFieldTrialName, key); 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 59116680a4aac90f2aa7413d9095a592090648e557Ben MurdochGURL BuildBlacklistRequestURL(const std::string& blacklist_url_prefix, 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const GURL& candidate_url) { 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return GURL(blacklist_url_prefix + 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::EscapeQueryParamValue(candidate_url.spec(), true)); 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Runs each callback in |requestors| on |suggestions|, then deallocates 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |requestors|. 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void DispatchRequestsAndClear( 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const SuggestionsProfile& suggestions, 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<SuggestionsService::ResponseCallback>* requestors) { 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<SuggestionsService::ResponseCallback>::iterator it; 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (it = requestors->begin(); it != requestors->end(); ++it) { 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!it->is_null()) it->Run(suggestions); 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<SuggestionsService::ResponseCallback>().swap(*requestors); 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const int kDefaultRequestTimeoutMs = 200; 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Default delay used when scheduling a blacklist request. 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst int kBlacklistDefaultDelaySec = 1; 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Multiplier on the delay used when scheduling a blacklist request, in case the 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// last observed request was unsuccessful. 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst int kBlacklistBackoffMultiplier = 2; 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Maximum valid delay for scheduling a request. Candidate delays larger than 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// this are rejected. This means the maximum backoff is at least 300 / 2, i.e. 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// 2.5 minutes. 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst int kBlacklistMaxDelaySec = 300; // 5 minutes 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSuggestionsFieldTrialName[] = "ChromeSuggestions"; 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSuggestionsFieldTrialURLParam[] = "url"; 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kSuggestionsFieldTrialCommonParamsParam[] = "common_params"; 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kSuggestionsFieldTrialBlacklistPathParam[] = "blacklist_path"; 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kSuggestionsFieldTrialBlacklistUrlParam[] = "blacklist_url_param"; 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSuggestionsFieldTrialStateParam[] = "state"; 996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)const char kSuggestionsFieldTrialControlParam[] = "control"; 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSuggestionsFieldTrialStateEnabled[] = "enabled"; 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kSuggestionsFieldTrialTimeoutMs[] = "timeout_ms"; 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// The default expiry timeout is 72 hours. 1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const int64 kDefaultExpiryUsec = 72 * base::Time::kMicrosecondsPerHour; 1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstd::string GetBlacklistUrlPrefix() { 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::stringstream blacklist_url_prefix_stream; 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blacklist_url_prefix_stream 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << GetExperimentParam(kSuggestionsFieldTrialURLParam) 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << GetExperimentParam(kSuggestionsFieldTrialBlacklistPathParam) << "?" 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << GetExperimentParam(kSuggestionsFieldTrialCommonParamsParam) << "&" 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << GetExperimentParam(kSuggestionsFieldTrialBlacklistUrlParam) << "="; 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return blacklist_url_prefix_stream.str(); 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SuggestionsService::SuggestionsService( 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::URLRequestContextGetter* url_request_context, 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<SuggestionsStore> suggestions_store, 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<ImageManager> thumbnail_manager, 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<BlacklistStore> blacklist_store) 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : suggestions_store_(suggestions_store.Pass()), 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blacklist_store_(blacklist_store.Pass()), 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch thumbnail_manager_(thumbnail_manager.Pass()), 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch url_request_context_(url_request_context), 129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blacklist_delay_sec_(kBlacklistDefaultDelaySec), 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci request_timeout_ms_(kDefaultRequestTimeoutMs), 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_(this) { 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Obtain various parameters from Variations. 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) suggestions_url_ = 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam) + "?" + 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetExperimentParam(kSuggestionsFieldTrialCommonParamsParam)); 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blacklist_url_prefix_ = GetBlacklistUrlPrefix(); 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string timeout = GetExperimentParam(kSuggestionsFieldTrialTimeoutMs); 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int temp_timeout; 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!timeout.empty() && base::StringToInt(timeout, &temp_timeout)) { 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) request_timeout_ms_ = temp_timeout; 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SuggestionsService::~SuggestionsService() {} 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SuggestionsService::IsEnabled() { 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return GetExperimentParam(kSuggestionsFieldTrialStateParam) == 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kSuggestionsFieldTrialStateEnabled; 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// static 1536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)bool SuggestionsService::IsControlGroup() { 1546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return GetExperimentParam(kSuggestionsFieldTrialControlParam) == 1556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) kSuggestionsFieldTrialStateEnabled; 1566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 1576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SuggestionsService::FetchSuggestionsData( 15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SyncState sync_state, 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SuggestionsService::ResponseCallback callback) { 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (sync_state == NOT_INITIALIZED_ENABLED) { 16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Sync is not initialized yet, but enabled. Serve previously cached 16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // suggestions if available. 16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) waiting_requestors_.push_back(callback); 16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ServeFromCache(); 16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else if (sync_state == SYNC_OR_HISTORY_SYNC_DISABLED) { 16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Cancel any ongoing request (and the timeout closure). We must no longer 17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // interact with the server. 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) pending_request_.reset(NULL); 17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) pending_timeout_closure_.reset(NULL); 17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) suggestions_store_->ClearSuggestions(); 17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) callback.Run(SuggestionsProfile()); 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_); 17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FetchSuggestionsDataNoTimeout(callback); 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Post a task to serve the cached suggestions if the request hasn't completed 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // after some time. Cancels the previous such task, if one existed. 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pending_timeout_closure_.reset(new CancelableClosure(base::Bind( 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &SuggestionsService::OnRequestTimeout, weak_ptr_factory_.GetWeakPtr()))); 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::MessageLoopProxy::current()->PostDelayedTask( 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, pending_timeout_closure_->callback(), 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::TimeDelta::FromMilliseconds(request_timeout_ms_)); 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SuggestionsService::GetPageThumbnail( 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const GURL& url, 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Callback<void(const GURL&, const SkBitmap*)> callback) { 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) thumbnail_manager_->GetImageForURL(url, callback); 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void SuggestionsService::BlacklistURL( 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const GURL& candidate_url, 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const SuggestionsService::ResponseCallback& callback) { 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) waiting_requestors_.push_back(callback); 20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Blacklist locally, for immediate effect. 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!blacklist_store_->BlacklistUrl(candidate_url)) { 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DVLOG(1) << "Failed blacklisting attempt."; 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If there's an ongoing request, let it complete. 209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (pending_request_.get()) return; 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IssueRequest(BuildBlacklistRequestURL(blacklist_url_prefix_, candidate_url)); 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static 214116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool SuggestionsService::GetBlacklistedUrl(const net::URLFetcher& request, 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL* url) { 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool is_blacklist_request = StartsWithASCII(request.GetOriginalURL().spec(), 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetBlacklistUrlPrefix(), true); 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!is_blacklist_request) return false; 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Extract the blacklisted URL from the blacklist request. 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::string blacklisted; 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!net::GetValueForKeyInQuery( 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch request.GetOriginalURL(), 224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetExperimentParam(kSuggestionsFieldTrialBlacklistUrlParam), 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &blacklisted)) 226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL blacklisted_url(blacklisted); 229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blacklisted_url.Swap(url); 230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SuggestionsService::RegisterProfilePrefs( 235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) user_prefs::PrefRegistrySyncable* registry) { 236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SuggestionsStore::RegisterProfilePrefs(registry); 237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BlacklistStore::RegisterProfilePrefs(registry); 238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void SuggestionsService::SetDefaultExpiryTimestamp( 24103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SuggestionsProfile* suggestions, int64 default_timestamp_usec) { 24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (int i = 0; i < suggestions->suggestions_size(); ++i) { 24303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ChromeSuggestion* suggestion = suggestions->mutable_suggestions(i); 24403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Do not set expiry if the server has already provided a more specific 24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // expiry time for this suggestion. 24603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!suggestion->has_expiry_ts()) { 24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) suggestion->set_expiry_ts(default_timestamp_usec); 24803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void SuggestionsService::FetchSuggestionsDataNoTimeout( 25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SuggestionsService::ResponseCallback callback) { 25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (pending_request_.get()) { 25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Request already exists, so just add requestor to queue. 25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) waiting_requestors_.push_back(callback); 25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Form new request. 26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(waiting_requestors_.empty()); 26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) waiting_requestors_.push_back(callback); 26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) IssueRequest(suggestions_url_); 26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 267116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SuggestionsService::IssueRequest(const GURL& url) { 268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_request_.reset(CreateSuggestionsRequest(url)); 269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_request_->Start(); 270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch last_request_started_time_ = base::TimeTicks::Now(); 271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 273116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnet::URLFetcher* SuggestionsService::CreateSuggestionsRequest(const GURL& url) { 274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::URLFetcher* request = 275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::URLFetcher::Create(0, url, net::URLFetcher::GET, this); 276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch request->SetLoadFlags(net::LOAD_DISABLE_CACHE); 277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch request->SetRequestContext(url_request_context_); 278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Add Chrome experiment state to the request headers. 279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::HttpRequestHeaders headers; 280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( 281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch request->GetOriginalURL(), false, false, &headers); 282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch request->SetExtraRequestHeaders(headers.ToString()); 283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return request; 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SuggestionsService::OnRequestTimeout() { 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ServeFromCache(); 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) { 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(pending_request_.get(), source); 294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // We no longer need the timeout closure. Delete it whether or not it has run. 295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If it hasn't, this cancels it. 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pending_timeout_closure_.reset(); 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The fetcher will be deleted when the request is handled. 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<const net::URLFetcher> request(pending_request_.release()); 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const net::URLRequestStatus& request_status = request->GetStatus(); 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (request_status.status() != net::URLRequestStatus::SUCCESS) { 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode", 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) -request_status.error()); 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Suggestions server request failed with error: " 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << request_status.error() << ": " 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << net::ErrorToString(request_status.error()); 307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Dispatch the cached profile on error. 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ServeFromCache(); 309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScheduleBlacklistUpload(false); 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Log the response code. 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const int response_code = request->GetResponseCode(); 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FetchResponseCode", response_code); 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (response_code != net::HTTP_OK) { 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Aggressively clear the store. 318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) suggestions_store_->ClearSuggestions(); 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_); 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScheduleBlacklistUpload(false); 321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::TimeDelta latency = 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeTicks::Now() - last_request_started_time_; 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_MEDIUM_TIMES("Suggestions.FetchSuccessLatency", latency); 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Handle a successful blacklisting. 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL blacklisted_url; 330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (GetBlacklistedUrl(*source, &blacklisted_url)) { 331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blacklist_store_->RemoveUrl(blacklisted_url); 332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string suggestions_data; 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success = request->GetResponseAsString(&suggestions_data); 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(success); 337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Compute suggestions, and dispatch them to requestors. On error still 339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // dispatch empty suggestions. 340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SuggestionsProfile suggestions; 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (suggestions_data.empty()) { 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LogResponseState(RESPONSE_EMPTY); 343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) suggestions_store_->ClearSuggestions(); 344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (suggestions.ParseFromString(suggestions_data)) { 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LogResponseState(RESPONSE_VALID); 3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) thumbnail_manager_->Initialize(suggestions); 3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int64 now_usec = (base::Time::NowFromSystemTime() - base::Time::UnixEpoch()) 3496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) .ToInternalValue(); 3506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SetDefaultExpiryTimestamp(&suggestions, now_usec + kDefaultExpiryUsec); 351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) suggestions_store_->StoreSuggestions(suggestions); 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LogResponseState(RESPONSE_INVALID); 354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) suggestions_store_->LoadSuggestions(&suggestions); 3556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) thumbnail_manager_->Initialize(suggestions); 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 358116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FilterAndServe(&suggestions); 359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScheduleBlacklistUpload(true); 360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SuggestionsService::Shutdown() { 363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Cancel pending request and timeout closure, then serve existing requestors 364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // from cache. 365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_request_.reset(NULL); 366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pending_timeout_closure_.reset(NULL); 367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ServeFromCache(); 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 370116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SuggestionsService::ServeFromCache() { 371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SuggestionsProfile suggestions; 372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch suggestions_store_->LoadSuggestions(&suggestions); 3736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) thumbnail_manager_->Initialize(suggestions); 374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FilterAndServe(&suggestions); 37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 377116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SuggestionsService::FilterAndServe(SuggestionsProfile* suggestions) { 378116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blacklist_store_->FilterSuggestions(suggestions); 379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DispatchRequestsAndClear(*suggestions, &waiting_requestors_); 38046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 38146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 382116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SuggestionsService::ScheduleBlacklistUpload(bool last_request_successful) { 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch UpdateBlacklistDelay(last_request_successful); 386116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Schedule a blacklist upload task. 388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL blacklist_url; 389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (blacklist_store_->GetFirstUrlFromBlacklist(&blacklist_url)) { 390116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Closure blacklist_cb = 391116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&SuggestionsService::UploadOneFromBlacklist, 392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_ptr_factory_.GetWeakPtr()); 3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::MessageLoopProxy::current()->PostDelayedTask( 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, blacklist_cb, 395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeDelta::FromSeconds(blacklist_delay_sec_)); 396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 399116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SuggestionsService::UploadOneFromBlacklist() { 4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If there's an ongoing request, let it complete. 403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (pending_request_.get()) return; 404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL blacklist_url; 406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!blacklist_store_->GetFirstUrlFromBlacklist(&blacklist_url)) 407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; // Local blacklist is empty. 408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Send blacklisting request. 410116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IssueRequest(BuildBlacklistRequestURL(blacklist_url_prefix_, blacklist_url)); 411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 413116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SuggestionsService::UpdateBlacklistDelay(bool last_request_successful) { 4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (last_request_successful) { 417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blacklist_delay_sec_ = kBlacklistDefaultDelaySec; 418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int candidate_delay = blacklist_delay_sec_ * kBlacklistBackoffMultiplier; 420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (candidate_delay < kBlacklistMaxDelaySec) 421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blacklist_delay_sec_ = candidate_delay; 422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace suggestions 426