summaryrefslogtreecommitdiffstats
path: root/components/search_provider_logos/logo_tracker.h
diff options
context:
space:
mode:
authornewt@chromium.org <newt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-30 21:55:16 +0000
committernewt@chromium.org <newt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-30 21:55:16 +0000
commit12fad44d9e65df34ef7f71f53bf16e0d429a8aff (patch)
treed2199704d6e10040a68faba57c4ee89bbf02994a /components/search_provider_logos/logo_tracker.h
parent09bd7bc27cf7544bdfb58fe0e21465b6485d599e (diff)
downloadchromium_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.h233
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_