Home | History | Annotate | Download | only in suggestions
      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
      3 // found in the LICENSE file.
      4 
      5 #ifndef COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_
      6 #define COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_
      7 
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/callback.h"
     13 #include "base/cancelable_callback.h"
     14 #include "base/gtest_prod_util.h"
     15 #include "base/memory/scoped_ptr.h"
     16 #include "base/memory/weak_ptr.h"
     17 #include "base/threading/thread_checker.h"
     18 #include "base/time/time.h"
     19 #include "components/keyed_service/core/keyed_service.h"
     20 #include "components/suggestions/image_manager.h"
     21 #include "components/suggestions/proto/suggestions.pb.h"
     22 #include "components/suggestions/suggestions_utils.h"
     23 #include "net/url_request/url_fetcher_delegate.h"
     24 #include "ui/gfx/image/image_skia.h"
     25 #include "url/gurl.h"
     26 
     27 namespace net {
     28 class URLRequestContextGetter;
     29 }  // namespace net
     30 
     31 namespace user_prefs {
     32 class PrefRegistrySyncable;
     33 }  // namespace user_prefs
     34 
     35 namespace suggestions {
     36 
     37 class BlacklistStore;
     38 class SuggestionsStore;
     39 
     40 extern const char kSuggestionsFieldTrialName[];
     41 extern const char kSuggestionsFieldTrialURLParam[];
     42 extern const char kSuggestionsFieldTrialCommonParamsParam[];
     43 extern const char kSuggestionsFieldTrialBlacklistPathParam[];
     44 extern const char kSuggestionsFieldTrialBlacklistUrlParam[];
     45 extern const char kSuggestionsFieldTrialStateParam[];
     46 extern const char kSuggestionsFieldTrialControlParam[];
     47 extern const char kSuggestionsFieldTrialStateEnabled[];
     48 extern const int64 kDefaultExpiryUsec;
     49 
     50 // An interface to fetch server suggestions asynchronously.
     51 class SuggestionsService : public KeyedService, public net::URLFetcherDelegate {
     52  public:
     53   typedef base::Callback<void(const SuggestionsProfile&)> ResponseCallback;
     54 
     55   SuggestionsService(
     56       net::URLRequestContextGetter* url_request_context,
     57       scoped_ptr<SuggestionsStore> suggestions_store,
     58       scoped_ptr<ImageManager> thumbnail_manager,
     59       scoped_ptr<BlacklistStore> blacklist_store);
     60   virtual ~SuggestionsService();
     61 
     62   // Whether this service is enabled.
     63   static bool IsEnabled();
     64 
     65   // Whether the user is part of a control group.
     66   static bool IsControlGroup();
     67 
     68   // Request suggestions data, which will be passed to |callback|. |sync_state|
     69   // will influence the behavior of this function (see SyncState definition).
     70   //
     71   // |sync_state| must be specified based on the current state of the system
     72   // (see suggestions::GetSyncState). Callers should call this function again if
     73   // sync state changes.
     74   //
     75   // If state allows for a network request, it is initiated unless a pending one
     76   // exists. To prevent multiple requests, all |callback|s are placed in a queue
     77   // and are updated simultaneously when the fetch completes. Also posts a task
     78   // to execute OnRequestTimeout if the request hasn't completed in a given
     79   // amount of time.
     80   void FetchSuggestionsData(SyncState sync_state,
     81                             ResponseCallback callback);
     82 
     83   // Retrieves stored thumbnail for website |url| asynchronously. Calls
     84   // |callback| with Bitmap pointer if found, and NULL otherwise.
     85   void GetPageThumbnail(
     86       const GURL& url,
     87       base::Callback<void(const GURL&, const SkBitmap*)> callback);
     88 
     89   // Issue a blacklist request. If there is already a blacklist request
     90   // in flight, the new blacklist request is ignored.
     91   void BlacklistURL(const GURL& candidate_url,
     92                     const ResponseCallback& callback);
     93 
     94   // Determines which URL a blacklist request was for, irrespective of the
     95   // request's status. Returns false if |request| is not a blacklist request.
     96   static bool GetBlacklistedUrl(const net::URLFetcher& request, GURL* url);
     97 
     98   // Register SuggestionsService related prefs in the Profile prefs.
     99   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
    100 
    101   // Sets default timestamp for suggestions which do not have expiry timestamp.
    102   void SetDefaultExpiryTimestamp(SuggestionsProfile* suggestions,
    103                                  int64 timestamp_usec);
    104  private:
    105   friend class SuggestionsServiceTest;
    106   FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, BlacklistURLFails);
    107   FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, FetchSuggestionsData);
    108   FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, UpdateBlacklistDelay);
    109 
    110   // Similar to FetchSuggestionsData but doesn't post a task to execute
    111   // OnDelaySinceFetch.
    112   void FetchSuggestionsDataNoTimeout(ResponseCallback callback);
    113 
    114   // Issue a request.
    115   void IssueRequest(const GURL& url);
    116 
    117   // Creates a request to the suggestions service, properly setting headers.
    118   net::URLFetcher* CreateSuggestionsRequest(const GURL& url);
    119 
    120   // Called to service the requestors if the issued suggestions request has
    121   // not completed in a given amount of time.
    122   virtual void OnRequestTimeout();
    123 
    124   // net::URLFetcherDelegate implementation.
    125   // Called when fetch request completes. Parses the received suggestions data,
    126   // and dispatches them to callbacks stored in queue.
    127   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
    128 
    129   // KeyedService implementation.
    130   virtual void Shutdown() OVERRIDE;
    131 
    132   // Load the cached suggestions and service the requestors with them.
    133   void ServeFromCache();
    134 
    135   // Apply the local blacklist to |suggestions|, then serve the requestors.
    136   void FilterAndServe(SuggestionsProfile* suggestions);
    137 
    138   // Schedule a blacklisting request if the local blacklist isn't empty.
    139   // |last_request_successful| is used for exponentially backing off when
    140   // requests fail.
    141   void ScheduleBlacklistUpload(bool last_request_successful);
    142 
    143   // If the local blacklist isn't empty, pick a URL from it and issue a
    144   // blacklist request for it.
    145   void UploadOneFromBlacklist();
    146 
    147   // Updates |blacklist_delay_sec_| based on the success of the last request.
    148   void UpdateBlacklistDelay(bool last_request_successful);
    149 
    150   // Test seams.
    151   int blacklist_delay() const { return blacklist_delay_sec_; }
    152   void set_blacklist_delay(int delay) { blacklist_delay_sec_ = delay; }
    153 
    154   base::ThreadChecker thread_checker_;
    155 
    156   // The cache for the suggestions.
    157   scoped_ptr<SuggestionsStore> suggestions_store_;
    158 
    159   // The local cache for temporary blacklist, until uploaded to the server.
    160   scoped_ptr<BlacklistStore> blacklist_store_;
    161 
    162   // Contains the current suggestions fetch request. Will only have a value
    163   // while a request is pending, and will be reset by |OnURLFetchComplete|.
    164   scoped_ptr<net::URLFetcher> pending_request_;
    165 
    166   // A closure that is run on a timeout from issuing the suggestions fetch
    167   // request, if the request hasn't completed.
    168   scoped_ptr<base::CancelableClosure> pending_timeout_closure_;
    169 
    170   // The start time of the previous suggestions request. This is used to measure
    171   // the latency of requests. Initially zero.
    172   base::TimeTicks last_request_started_time_;
    173 
    174   // The URL to fetch suggestions data from.
    175   GURL suggestions_url_;
    176 
    177   // Prefix for building the blacklisting URL.
    178   std::string blacklist_url_prefix_;
    179 
    180   // Queue of callbacks. These are flushed when fetch request completes.
    181   std::vector<ResponseCallback> waiting_requestors_;
    182 
    183   // Used to obtain server thumbnails, if available.
    184   scoped_ptr<ImageManager> thumbnail_manager_;
    185 
    186   net::URLRequestContextGetter* url_request_context_;
    187 
    188   // Delay used when scheduling a blacklisting task.
    189   int blacklist_delay_sec_;
    190 
    191   // Timeout (in ms) before serving requestors after a fetch suggestions request
    192   // has been issued.
    193   int request_timeout_ms_;
    194 
    195   // For callbacks may be run after destruction.
    196   base::WeakPtrFactory<SuggestionsService> weak_ptr_factory_;
    197 
    198   DISALLOW_COPY_AND_ASSIGN(SuggestionsService);
    199 };
    200 
    201 }  // namespace suggestions
    202 
    203 #endif  // COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_
    204