diff options
author | newt@chromium.org <newt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-30 21:55:16 +0000 |
---|---|---|
committer | newt@chromium.org <newt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-30 21:55:16 +0000 |
commit | 12fad44d9e65df34ef7f71f53bf16e0d429a8aff (patch) | |
tree | d2199704d6e10040a68faba57c4ee89bbf02994a /components/search_provider_logos/logo_tracker.h | |
parent | 09bd7bc27cf7544bdfb58fe0e21465b6485d599e (diff) | |
download | chromium_src-12fad44d9e65df34ef7f71f53bf16e0d429a8aff.zip chromium_src-12fad44d9e65df34ef7f71f53bf16e0d429a8aff.tar.gz chromium_src-12fad44d9e65df34ef7f71f53bf16e0d429a8aff.tar.bz2 |
Add LogoTracker to fetch search providers' logos.
The LogoTracker keeps track of the logo for a search provider. The logo
is downloaded, cached on disk, and periodically revalidated.
This code lives inside a component (search_provider_logos) so it can be
used on both Android and iOS.
BUG=178922
NOTRY=true
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=267314
Review URL: https://codereview.chromium.org/162373002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267349 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/search_provider_logos/logo_tracker.h')
-rw-r--r-- | components/search_provider_logos/logo_tracker.h | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/components/search_provider_logos/logo_tracker.h b/components/search_provider_logos/logo_tracker.h new file mode 100644 index 0000000..8a80bd6 --- /dev/null +++ b/components/search_provider_logos/logo_tracker.h @@ -0,0 +1,233 @@ +// 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_SEARCH_PROVIDER_LOGOS_LOGO_TRACKER_H_ +#define COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_TRACKER_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "base/sequenced_task_runner.h" +#include "base/time/clock.h" +#include "base/time/time.h" +#include "components/search_provider_logos/logo_cache.h" +#include "components/search_provider_logos/logo_common.h" +#include "net/url_request/url_fetcher_delegate.h" +#include "url/gurl.h" + +namespace net { +class URLFetcher; +class URLRequestContextGetter; +} + +namespace search_provider_logos { + +// Receives updates when the search provider's logo is available. +class LogoObserver { + public: + virtual ~LogoObserver() {} + + // Called when the cached logo is available and possibly when a freshly + // downloaded logo is available. |logo| will be NULL if no logo is available. + // |from_cache| indicates whether the logo was loaded from the cache. + // + // If the fresh logo is the same as the cached logo, this will not be called + // again. + virtual void OnLogoAvailable(const Logo* logo, bool from_cache) = 0; + + // Called when the LogoTracker will no longer send updates to this + // LogoObserver. For example: after the cached logo is validated, after + // OnFreshLogoAvailable() is called, or when the LogoTracker is destructed. + // This is not called when an observer is removed using + // LogoTracker::RemoveObserver(). + virtual void OnObserverRemoved() = 0; +}; + +// Provides a LogoTracker with methods it needs to download and cache logos. +class LogoDelegate { + public: + virtual ~LogoDelegate() {} + + // Decodes an untrusted image safely and returns it as an SkBitmap via + // |image_decoded_callback|. If image decoding fails, |image_decoded_callback| + // should be called with NULL. This will be called on the thread that + // LogoTracker lives on and |image_decoded_callback| must be called on the + // same thread. + virtual void DecodeUntrustedImage( + const scoped_refptr<base::RefCountedString>& encoded_image, + base::Callback<void(const SkBitmap&)> image_decoded_callback) = 0; +}; + +// Parses the response from the server and returns it as an EncodedLogo. Returns +// NULL if the response is invalid. +typedef base::Callback< + scoped_ptr<EncodedLogo>(const scoped_ptr<std::string>& response, + base::Time response_time)> ParseLogoResponse; + +// Encodes the fingerprint of the cached logo in the logo URL. This enables the +// server to verify whether the cached logo is up-to-date. +typedef base::Callback< + GURL(const GURL& logo_url, const std::string& fingerprint)> + AppendFingerprintToLogoURL; + +// This class provides the logo for a search provider. Logos are downloaded from +// the search provider's logo URL and cached on disk. +// +// Call SetServerAPI() at least once to specify how to get the logo from the +// server. Then call GetLogo() to trigger retrieval of the logo and receive +// updates once the cached and/or fresh logos are available. +class LogoTracker : public net::URLFetcherDelegate { + public: + // Constructs a LogoTracker with the given LogoDelegate. Takes ownership of + // |delegate|, which will be deleted at the same time as the LogoTracker. + // + // |cached_logo_directory| is the directory in which the cached logo and its + // metadata should be saved. + // + // |file_task_runner| is the SequencedTaskRunner that should be used to run + // file system operations. + // + // |background_task_runner| is the TaskRunner that should be used to for + // CPU-intensive background operations. + // + // |request_context_getter| is the URLRequestContextGetter used to download + // the logo. + explicit LogoTracker( + base::FilePath cached_logo_directory, + scoped_refptr<base::SequencedTaskRunner> file_task_runner, + scoped_refptr<base::TaskRunner> background_task_runner, + scoped_refptr<net::URLRequestContextGetter> request_context_getter, + scoped_ptr<LogoDelegate> delegate); + + virtual ~LogoTracker(); + + // Defines the server API for downloading and parsing the logo. This must be + // called at least once before calling GetLogo(). + // + // |logo_url| is the URL from which the logo will be downloaded. If |logo_url| + // is different than the current logo URL, any pending LogoObservers will be + // canceled. + // + // |parse_logo_response_func| is a callback that will be used to parse the + // server's response into a EncodedLogo object. |append_fingerprint_func| is a + // callback that will return the URL from which to download the logo if a + // cached logo with a fingerprint is already available. Note: + // |parse_logo_response_func| and |append_fingerprint_func| must be suitable + // for running multiple times, concurrently, and on multiple threads. + void SetServerAPI(const GURL& logo_url, + const ParseLogoResponse& parse_logo_response_func, + const AppendFingerprintToLogoURL& append_fingerprint_func); + + // Retrieves the current search provider's logo from the local cache and/or + // over the network, and registers |observer| to be called when the cached + // and/or fresh logos are available. + void GetLogo(LogoObserver* observer); + + // Prevents |observer| from receiving future updates. This is safe to call + // even when the observer is being notified of an update. + void RemoveObserver(LogoObserver* observer); + + // Overrides the cache used to store logos. + void SetLogoCacheForTests(scoped_ptr<LogoCache> cache); + + // Overrides the clock used to check the time. + void SetClockForTests(scoped_ptr<base::Clock> clock); + + private: + // Cancels the current asynchronous operation, if any, and resets all member + // variables that change as the logo is fetched. + void ReturnToIdle(); + + // Called when the cached logo has been read from the cache. |cached_logo| + // will be NULL if there wasn't a valid, up-to-date logo in the cache. + void OnCachedLogoRead(scoped_ptr<EncodedLogo> cached_logo); + + // Called when the cached logo has been decoded into an SkBitmap. |image| will + // be NULL if decoding failed. + void OnCachedLogoAvailable(const LogoMetadata& metadata, + const SkBitmap& image); + + // Stores |logo| in the cache. + void SetCachedLogo(scoped_ptr<EncodedLogo> logo); + + // Updates the metadata for the logo already stored in the cache. + void SetCachedMetadata(const LogoMetadata& metadata); + + // Starts fetching the current logo over the network. + void FetchLogo(); + + // Called when the logo has been downloaded and parsed. |logo| will be NULL + // if the server's response was invalid. + void OnFreshLogoParsed(scoped_ptr<EncodedLogo> logo); + + // Called when the fresh logo has been decoded into an SkBitmap. |image| will + // be NULL if decoding failed. + void OnFreshLogoAvailable(scoped_ptr<EncodedLogo> logo, + const SkBitmap& image); + + // net::URLFetcherDelegate: + virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; + virtual void OnURLFetchDownloadProgress(const net::URLFetcher* source, + int64 current, + int64 total) OVERRIDE; + + // The URL from which the logo is fetched. + GURL logo_url_; + + // The function used to parse the logo response from the server. + ParseLogoResponse parse_logo_response_func_; + + // The function used to include the cached logo's fingerprint in the logo URL. + AppendFingerprintToLogoURL append_fingerprint_func_; + + // False if an asynchronous task is currently running. + bool is_idle_; + + // The logo that's been read from the cache, or NULL if the cache is empty. + // Meaningful only if is_cached_logo_valid_ is true; NULL otherwise. + scoped_ptr<Logo> cached_logo_; + + // Whether the value of |cached_logo_| reflects the actual cached logo. + // This will be false if the logo hasn't been read from the cache yet. + // |cached_logo_| may be NULL even if |is_cached_logo_valid_| is true, if no + // logo is cached. + bool is_cached_logo_valid_; + + // The URLFetcher currently fetching the logo. NULL when not fetching. + scoped_ptr<net::URLFetcher> fetcher_; + + // The list of observers to be notified when the logo is available. This + // should be empty when the state is IDLE. + ObserverList<LogoObserver> logo_observers_; + + scoped_ptr<LogoDelegate> logo_delegate_; + + // The cache used to persist the logo on disk. Used only on the file thread. + LogoCache* logo_cache_; + + // Clock used to determine current time. Can be overridden in tests. + scoped_ptr<base::Clock> clock_; + + // The SequencedTaskRunner on which file system operations will be run. + scoped_refptr<base::SequencedTaskRunner> file_task_runner_; + + // The TaskRunner on which the server's response will be parsed. + scoped_refptr<base::TaskRunner> background_task_runner_; + + // The URLRequestContextGetter used for network requests. + scoped_refptr<net::URLRequestContextGetter> request_context_getter_; + + base::WeakPtrFactory<LogoTracker> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(LogoTracker); +}; + +} // namespace search_provider_logos + +#endif // COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_TRACKER_H_ |