C++程序  |  204行  |  7.66 KB

// 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.

#ifndef COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_
#define COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_

#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 {
 public:
  typedef base::Callback<void(const SuggestionsProfile&)> ResponseCallback;

  SuggestionsService(
      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);
 private:
  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_;

  // Timeout (in ms) before serving requestors after a fetch suggestions request
  // has been issued.
  int request_timeout_ms_;

  // For callbacks may be run after destruction.
  base::WeakPtrFactory<SuggestionsService> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(SuggestionsService);
};

}  // namespace suggestions

#endif  // COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_