blob: e495f7f8aac23fd5dc46fd541355be7027e45097 [file] [log] [blame]
// 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 <string>
#include <vector>
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/cancelable_callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/suggestions/image_manager.h"
#include "components/suggestions/proto/suggestions.pb.h"
#include "components/suggestions/suggestions_utils.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "ui/gfx/image/image_skia.h"
#include "url/gurl.h"
namespace net {
class URLRequestContextGetter;
} // namespace net
namespace user_prefs {
class PrefRegistrySyncable;
} // namespace user_prefs
namespace suggestions {
class BlacklistStore;
class SuggestionsStore;
extern const char kSuggestionsFieldTrialName[];
extern const char kSuggestionsFieldTrialURLParam[];
extern const char kSuggestionsFieldTrialCommonParamsParam[];
extern const char kSuggestionsFieldTrialBlacklistPathParam[];
extern const char kSuggestionsFieldTrialBlacklistUrlParam[];
extern const char kSuggestionsFieldTrialStateParam[];
extern const char kSuggestionsFieldTrialControlParam[];
extern const char kSuggestionsFieldTrialStateEnabled[];
extern const int64 kDefaultExpiryUsec;
// An interface to fetch server suggestions asynchronously.
class SuggestionsService : public KeyedService, public net::URLFetcherDelegate {
typedef base::Callback<void(const SuggestionsProfile&)> ResponseCallback;
net::URLRequestContextGetter* url_request_context,
scoped_ptr<SuggestionsStore> suggestions_store,
scoped_ptr<ImageManager> thumbnail_manager,
scoped_ptr<BlacklistStore> blacklist_store);
virtual ~SuggestionsService();
// Whether this service is enabled.
static bool IsEnabled();
// Whether the user is part of a control group.
static bool IsControlGroup();
// Request suggestions data, which will be passed to |callback|. |sync_state|
// will influence the behavior of this function (see SyncState definition).
// |sync_state| must be specified based on the current state of the system
// (see suggestions::GetSyncState). Callers should call this function again if
// sync state changes.
// If state allows for a network request, it is initiated unless a pending one
// exists. To prevent multiple requests, all |callback|s are placed in a queue
// and are updated simultaneously when the fetch completes. Also posts a task
// to execute OnRequestTimeout if the request hasn't completed in a given
// amount of time.
void FetchSuggestionsData(SyncState sync_state,
ResponseCallback callback);
// Retrieves stored thumbnail for website |url| asynchronously. Calls
// |callback| with Bitmap pointer if found, and NULL otherwise.
void GetPageThumbnail(
const GURL& url,
base::Callback<void(const GURL&, const SkBitmap*)> callback);
// Issue a blacklist request. If there is already a blacklist request
// in flight, the new blacklist request is ignored.
void BlacklistURL(const GURL& candidate_url,
const ResponseCallback& callback);
// Determines which URL a blacklist request was for, irrespective of the
// request's status. Returns false if |request| is not a blacklist request.
static bool GetBlacklistedUrl(const net::URLFetcher& request, GURL* url);
// Register SuggestionsService related prefs in the Profile prefs.
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// Sets default timestamp for suggestions which do not have expiry timestamp.
void SetDefaultExpiryTimestamp(SuggestionsProfile* suggestions,
int64 timestamp_usec);
friend class SuggestionsServiceTest;
FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, BlacklistURLFails);
FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, FetchSuggestionsData);
FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, UpdateBlacklistDelay);
// Similar to FetchSuggestionsData but doesn't post a task to execute
// OnDelaySinceFetch.
void FetchSuggestionsDataNoTimeout(ResponseCallback callback);
// Issue a request.
void IssueRequest(const GURL& url);
// Creates a request to the suggestions service, properly setting headers.
net::URLFetcher* CreateSuggestionsRequest(const GURL& url);
// Called to service the requestors if the issued suggestions request has
// not completed in a given amount of time.
virtual void OnRequestTimeout();
// net::URLFetcherDelegate implementation.
// Called when fetch request completes. Parses the received suggestions data,
// and dispatches them to callbacks stored in queue.
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
// KeyedService implementation.
virtual void Shutdown() OVERRIDE;
// Load the cached suggestions and service the requestors with them.
void ServeFromCache();
// Apply the local blacklist to |suggestions|, then serve the requestors.
void FilterAndServe(SuggestionsProfile* suggestions);
// Schedule a blacklisting request if the local blacklist isn't empty.
// |last_request_successful| is used for exponentially backing off when
// requests fail.
void ScheduleBlacklistUpload(bool last_request_successful);
// If the local blacklist isn't empty, pick a URL from it and issue a
// blacklist request for it.
void UploadOneFromBlacklist();
// Updates |blacklist_delay_sec_| based on the success of the last request.
void UpdateBlacklistDelay(bool last_request_successful);
// Test seams.
int blacklist_delay() const { return blacklist_delay_sec_; }
void set_blacklist_delay(int delay) { blacklist_delay_sec_ = delay; }
base::ThreadChecker thread_checker_;
// The cache for the suggestions.
scoped_ptr<SuggestionsStore> suggestions_store_;
// The local cache for temporary blacklist, until uploaded to the server.
scoped_ptr<BlacklistStore> blacklist_store_;
// Contains the current suggestions fetch request. Will only have a value
// while a request is pending, and will be reset by |OnURLFetchComplete|.
scoped_ptr<net::URLFetcher> pending_request_;
// A closure that is run on a timeout from issuing the suggestions fetch
// request, if the request hasn't completed.
scoped_ptr<base::CancelableClosure> pending_timeout_closure_;
// The start time of the previous suggestions request. This is used to measure
// the latency of requests. Initially zero.
base::TimeTicks last_request_started_time_;
// The URL to fetch suggestions data from.
GURL suggestions_url_;
// Prefix for building the blacklisting URL.
std::string blacklist_url_prefix_;
// Queue of callbacks. These are flushed when fetch request completes.
std::vector<ResponseCallback> waiting_requestors_;
// Used to obtain server thumbnails, if available.
scoped_ptr<ImageManager> thumbnail_manager_;
net::URLRequestContextGetter* url_request_context_;
// Delay used when scheduling a blacklisting task.
int blacklist_delay_sec_;
// For callbacks may be run after destruction.
base::WeakPtrFactory<SuggestionsService> weak_ptr_factory_;
// Timeout (in ms) before serving requestors after a fetch suggestions request
// has been issued.
int request_timeout_ms_;
} // namespace suggestions