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.
5 #ifndef COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_TRACKER_H_
6 #define COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_TRACKER_H_
11 #include "base/callback.h"
12 #include "base/files/file_path.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/observer_list.h"
16 #include "base/sequenced_task_runner.h"
17 #include "base/time/clock.h"
18 #include "base/time/time.h"
19 #include "components/search_provider_logos/logo_cache.h"
20 #include "components/search_provider_logos/logo_common.h"
21 #include "net/url_request/url_fetcher_delegate.h"
26 class URLRequestContextGetter
;
29 namespace search_provider_logos
{
31 // Receives updates when the search provider's logo is available.
34 virtual ~LogoObserver() {}
36 // Called when the cached logo is available and possibly when a freshly
37 // downloaded logo is available. |logo| will be NULL if no logo is available.
38 // |from_cache| indicates whether the logo was loaded from the cache.
40 // If the fresh logo is the same as the cached logo, this will not be called
42 virtual void OnLogoAvailable(const Logo
* logo
, bool from_cache
) = 0;
44 // Called when the LogoTracker will no longer send updates to this
45 // LogoObserver. For example: after the cached logo is validated, after
46 // OnFreshLogoAvailable() is called, or when the LogoTracker is destructed.
47 // This is not called when an observer is removed using
48 // LogoTracker::RemoveObserver().
49 virtual void OnObserverRemoved() = 0;
52 // Provides a LogoTracker with methods it needs to download and cache logos.
55 virtual ~LogoDelegate() {}
57 // Decodes an untrusted image safely and returns it as an SkBitmap via
58 // |image_decoded_callback|. If image decoding fails, |image_decoded_callback|
59 // should be called with NULL. This will be called on the thread that
60 // LogoTracker lives on and |image_decoded_callback| must be called on the
62 virtual void DecodeUntrustedImage(
63 const scoped_refptr
<base::RefCountedString
>& encoded_image
,
64 base::Callback
<void(const SkBitmap
&)> image_decoded_callback
) = 0;
67 // Parses the response from the server and returns it as an EncodedLogo. Returns
68 // NULL if the response is invalid.
69 typedef base::Callback
<
70 scoped_ptr
<EncodedLogo
>(const scoped_ptr
<std::string
>& response
,
71 base::Time response_time
)> ParseLogoResponse
;
73 // Encodes the fingerprint of the cached logo in the logo URL. This enables the
74 // server to verify whether the cached logo is up-to-date.
75 typedef base::Callback
<GURL(const GURL
& logo_url
,
76 const std::string
& fingerprint
,
77 bool wants_cta
)> AppendQueryparamsToLogoURL
;
79 // This class provides the logo for a search provider. Logos are downloaded from
80 // the search provider's logo URL and cached on disk.
82 // Call SetServerAPI() at least once to specify how to get the logo from the
83 // server. Then call GetLogo() to trigger retrieval of the logo and receive
84 // updates once the cached and/or fresh logos are available.
85 class LogoTracker
: public net::URLFetcherDelegate
{
87 // Constructs a LogoTracker with the given LogoDelegate. Takes ownership of
88 // |delegate|, which will be deleted at the same time as the LogoTracker.
90 // |cached_logo_directory| is the directory in which the cached logo and its
91 // metadata should be saved.
93 // |file_task_runner| is the SequencedTaskRunner that should be used to run
94 // file system operations.
96 // |background_task_runner| is the TaskRunner that should be used to for
97 // CPU-intensive background operations.
99 // |request_context_getter| is the URLRequestContextGetter used to download
101 explicit LogoTracker(
102 base::FilePath cached_logo_directory
,
103 scoped_refptr
<base::SequencedTaskRunner
> file_task_runner
,
104 scoped_refptr
<base::TaskRunner
> background_task_runner
,
105 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter
,
106 scoped_ptr
<LogoDelegate
> delegate
);
108 ~LogoTracker() override
;
110 // Defines the server API for downloading and parsing the logo. This must be
111 // called at least once before calling GetLogo().
113 // |logo_url| is the URL from which the logo will be downloaded. If |logo_url|
114 // is different than the current logo URL, any pending LogoObservers will be
117 // |parse_logo_response_func| is a callback that will be used to parse the
118 // server's response into a EncodedLogo object. |append_queryparams_func| is a
119 // callback that will return the URL from which to download the logo.
120 // |wants_cta| determines if the url should return a call to action image.
121 // Note: |parse_logo_response_func| and |append_queryparams_func| must be
122 // suitable for running multiple times, concurrently, and on multiple threads.
123 void SetServerAPI(const GURL
& logo_url
,
124 const ParseLogoResponse
& parse_logo_response_func
,
125 const AppendQueryparamsToLogoURL
& append_queryparams_func
,
128 // Retrieves the current search provider's logo from the local cache and/or
129 // over the network, and registers |observer| to be called when the cached
130 // and/or fresh logos are available.
131 void GetLogo(LogoObserver
* observer
);
133 // Prevents |observer| from receiving future updates. This is safe to call
134 // even when the observer is being notified of an update.
135 void RemoveObserver(LogoObserver
* observer
);
137 // Overrides the cache used to store logos.
138 void SetLogoCacheForTests(scoped_ptr
<LogoCache
> cache
);
140 // Overrides the clock used to check the time.
141 void SetClockForTests(scoped_ptr
<base::Clock
> clock
);
144 // Cancels the current asynchronous operation, if any, and resets all member
145 // variables that change as the logo is fetched.
148 // Called when the cached logo has been read from the cache. |cached_logo|
149 // will be NULL if there wasn't a valid, up-to-date logo in the cache.
150 void OnCachedLogoRead(scoped_ptr
<EncodedLogo
> cached_logo
);
152 // Called when the cached logo has been decoded into an SkBitmap. |image| will
153 // be NULL if decoding failed.
154 void OnCachedLogoAvailable(const LogoMetadata
& metadata
,
155 const SkBitmap
& image
);
157 // Stores |logo| in the cache.
158 void SetCachedLogo(scoped_ptr
<EncodedLogo
> logo
);
160 // Updates the metadata for the logo already stored in the cache.
161 void SetCachedMetadata(const LogoMetadata
& metadata
);
163 // Starts fetching the current logo over the network.
166 // Called when the logo has been downloaded and parsed. |logo| will be NULL
167 // if the server's response was invalid.
168 void OnFreshLogoParsed(scoped_ptr
<EncodedLogo
> logo
);
170 // Called when the fresh logo has been decoded into an SkBitmap. |image| will
171 // be NULL if decoding failed.
172 void OnFreshLogoAvailable(scoped_ptr
<EncodedLogo
> logo
,
173 const SkBitmap
& image
);
175 // net::URLFetcherDelegate:
176 void OnURLFetchComplete(const net::URLFetcher
* source
) override
;
177 void OnURLFetchDownloadProgress(const net::URLFetcher
* source
,
179 int64 total
) override
;
181 // The URL from which the logo is fetched.
184 // The function used to parse the logo response from the server.
185 ParseLogoResponse parse_logo_response_func_
;
187 // The function used to include the cached logo's fingerprint and call to
188 // action request in the logo URL.
189 AppendQueryparamsToLogoURL append_queryparams_func_
;
191 // If |true| request call to action in server API.
194 // False if an asynchronous task is currently running.
197 // The logo that's been read from the cache, or NULL if the cache is empty.
198 // Meaningful only if is_cached_logo_valid_ is true; NULL otherwise.
199 scoped_ptr
<Logo
> cached_logo_
;
201 // Whether the value of |cached_logo_| reflects the actual cached logo.
202 // This will be false if the logo hasn't been read from the cache yet.
203 // |cached_logo_| may be NULL even if |is_cached_logo_valid_| is true, if no
205 bool is_cached_logo_valid_
;
207 // The URLFetcher currently fetching the logo. NULL when not fetching.
208 scoped_ptr
<net::URLFetcher
> fetcher_
;
210 // The list of observers to be notified when the logo is available. This
211 // should be empty when the state is IDLE.
212 base::ObserverList
<LogoObserver
> logo_observers_
;
214 scoped_ptr
<LogoDelegate
> logo_delegate_
;
216 // The cache used to persist the logo on disk. Used only on the file thread.
217 LogoCache
* logo_cache_
;
219 // Clock used to determine current time. Can be overridden in tests.
220 scoped_ptr
<base::Clock
> clock_
;
222 // The SequencedTaskRunner on which file system operations will be run.
223 scoped_refptr
<base::SequencedTaskRunner
> file_task_runner_
;
225 // The TaskRunner on which the server's response will be parsed.
226 scoped_refptr
<base::TaskRunner
> background_task_runner_
;
228 // The URLRequestContextGetter used for network requests.
229 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter_
;
231 base::WeakPtrFactory
<LogoTracker
> weak_ptr_factory_
;
233 DISALLOW_COPY_AND_ASSIGN(LogoTracker
);
236 } // namespace search_provider_logos
238 #endif // COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_TRACKER_H_