Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: chrome/browser/installable/installable_checker.h

Issue 2160513002: Extract AppBannerDataFetcher into an InstallableManager. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use pending_tasks_ vector and invoke callbacks directly Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 CHROME_BROWSER_INSTALLABLE_INSTALLABLE_CHECKER_H_
6 #define CHROME_BROWSER_INSTALLABLE_INSTALLABLE_CHECKER_H_
7
8 #include <utility>
9
10 #include "base/callback_forward.h"
11 #include "base/gtest_prod_util.h"
12 #include "base/macros.h"
13 #include "base/memory/weak_ptr.h"
14 #include "chrome/browser/installable/installable_logging.h"
15 #include "content/public/browser/web_contents_observer.h"
16 #include "content/public/browser/web_contents_user_data.h"
17 #include "content/public/common/manifest.h"
18 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "url/gurl.h"
20
21 namespace installable {
22
23 // This struct specifies the work to be done by the InstallableChecker on the
24 // site loaded in the main frame of the WebContents to which it is attached.
25 // Results are cached and evaluated the order specified in this struct; if any
26 // previous step is requested and fails, no further steps will be performed.
27 // For example, if |has_valid_icon| and |has_service_worker| are both true,
28 // then the site's icon will only be fetched if a service worker was found.
29 // The checker will *always* look for a web app manifest first as this is
30 // required for all other resources.
31 struct InstallableParams {
32 // The ideal icon size that should be fetched. Used only if |has_valid_icon|
33 // is true.
34 int ideal_icon_size_in_dp;
35
36 // The minimum icon size that should be fetched. Used only if
37 // |has_valid_icon| is true.
38 int minimum_icon_size_in_dp;
39
40 // Check whether the site's manifest is valid for a web app. That is, the
41 // manifest:
42 // - is non-empty
43 // - has a valid start URL
44 // - has a non-null name OR a non-null short_name
45 // - has a display field set to "standalone" or "fullscreen"
46 // - contains a PNG icon of at least 144x144px
47 bool has_valid_webapp_manifest;
48
49 // Check whether the site has an active service worker controlling it and the
50 // manifest start URL.
51 bool has_service_worker;
52
53 // Check whether there is an icon in the manifest conforming to the icon size
54 // parameters, and that the icon can be fetched and isn't an empty bitmap.
55 bool has_valid_icon;
56
57 // The default constructor sets all bool parameters are set to false.
58 InstallableParams();
59 };
60
61 // This struct is passed to an InstallableCallback when the InstallableChecker
62 // has finished working. Each pointer/reference member is a reference to the
63 // data in InstallableChecker; the checker owns these resources.
64 // Callers should ensure that all fields they use in this result struct are
65 // requested in the original call to InstallableChecker::Start.
66 struct InstallableResult {
67 // This code will be NoErrorDetected if there were no issues.
68 const ErrorCode error_code;
69
70 // The manifest URL. If non-empty, the site specified a <link rel="manifest">
71 // tag.
72 const GURL& manifest_url;
73
74 // The manifest object. Empty if a manifest was not specified, or could not be
75 // parsed.
76 const content::Manifest& manifest;
77
78 // The URL of the most appropriate icon from the manifest.
79 const GURL& icon_url;
80
81 // The most appropriate icon from the manifest.
82 const SkBitmap* icon;
83
84 // True if the site has a manifest which is valid for a webapp.
85 const bool has_valid_webapp_manifest;
86
87 // True if the site has a service worker controlling the manifest start URL.
88 const bool has_service_worker;
89 };
90
91 // The callback type passed to InstallableChecker::Start. Invoked on the UI
92 // thread once the checker has performed all of the operations specified in the
93 // InstallableParams passed to Start.
94 using InstallableCallback = base::Callback<void(const InstallableResult&)>;
95
96 // This class is responsible for fetching the resources required to check and
97 // install a site. Minimally, this is a web app manifest for the document in the
98 // main frame; this manifest is all that is required for a site offering native
99 // app banners. Progressive web apps must have specific fields in the manifest
100 // set, a service worker controlling the manifest's start URL, and a valid,
101 // fetchable icon in the manifest. Sites which do not have a service worker may
102 // still specify a valid, fetchable icon in the manifest, and this will be used
103 // when the site is added to homescreen.
104 class InstallableChecker
105 : public content::WebContentsObserver,
106 public content::WebContentsUserData<InstallableChecker> {
107 public:
108 explicit InstallableChecker(content::WebContents* web_contents);
109 ~InstallableChecker() override;
110
111 // Returns true if the InstallableChecker is currently running.
112 bool IsActive() const { return HasFlag(STARTED); }
113
114 // Returns true if |manifest| meets the requirements for being installable.
115 // Sets |valid_webapp_manifest_error_| if any errors are encountered.
116 bool IsManifestValidForWebApp(const content::Manifest& manifest);
117
118 // Returns the minimum icon size in pixels for a site to be installable.
119 // TODO(dominickn): consolidate this concept with minimum_icon_size_in_dp
120 // across all platforms.
121 static int GetMinimumIconSizeInPx();
122
123 // Start the installable check, fetching the resources specified in |params|.
124 // |callback| is invoked on the UI thread when the checks are complete,
125 // passing an InstallableResult struct containing the requested resources.
126 //
127 // Separate calls to Start are processed serially; each call is guaranteed to
128 // invoke |callback| before the next one is processed. Resources are cached on
129 // this object: a previous call for the same page and with the same icon sizes
130 // will not perform duplicate work and will run the callback immediately with
131 // the cached resources. When |callback| runs, it should copy any resources on
132 // the result that are necessary for future work. It should also avoid running
133 // expensive tasks directly and defer them to later as the callback is
134 // directly invoked by the InstallableChecker to guarantee the consistency of
135 // the check results (i.e. the icon).
136 // This method is marked virtual so clients may mock this object in tests.
137 virtual void Start(const InstallableParams& params,
138 const InstallableCallback& callback);
139
140 private:
141 friend class InstallableCheckerUnitTest;
142 FRIEND_TEST_ALL_PREFIXES(InstallableCheckerBrowserTest,
143 CheckerBeginsInEmptyState);
144 FRIEND_TEST_ALL_PREFIXES(InstallableCheckerBrowserTest,
145 CheckWebapp);
146
147 // This pair holds the parameters for a request to Start, along with the
148 // callback to be invoked when the request parameters are fulfilled. This is
149 // cheaply copyable and will be held in a std::vector.
150 using Task = std::pair<InstallableParams, InstallableCallback>;
151
152 // Bit flags used to maintain internal state regarding what has and hasn't yet
153 // been fetched/computed.
154 enum StatusFlag : uint32_t {
155 DORMANT = 0,
156 STARTED = 1 << 0,
157 RUNNING_CALLBACKS = 1 << 1,
158 MANIFEST_FETCHED = 1 << 2,
159 MANIFEST_VALIDATED = 1 << 3,
160 ICON_FETCHED = 1 << 4,
161 SERVICE_WORKER_CHECKED = 1 << 5,
162 };
163
164 // Stops the checking pipeline for the current task. Does not cancel any other
165 // tasks which may be queued.
166 void Cancel();
167
168 // Returns true if the icon size in |params| match those currently being
169 // requested.
170 bool DoesIconSizeMatch(const InstallableParams& params) const;
171
172 // Returns the error code associated with the resources requested in |params|,
173 // or NoErrorDetected if there is no error.
174 ErrorCode GetErrorCode(const InstallableParams& params);
175
176 // Returns the WebContents to which this object is attached, or nullptr if the
177 // WebContents doesn't exist or is currently being destroyed.
178 content::WebContents* GetWebContents();
179
180 // Returns true if |params| requires no more work to be done (i.e. all the
181 // resources originally requested by |params| have been retrieved).
182 bool IsComplete(const InstallableParams& params) const;
183
184 // Returns true if |web_contents| is non-null and this checker remains active.
185 // If false is returned, |processing_error_| will be set.
186 bool IsRunning(content::WebContents* web_contents);
187
188 // Resets this object and removes all queued tasks. Called when navigating to
189 // a new page.
190 void Reset();
191
192 // Runs the callback associated with any task that is now complete.
193 void RunCallbacks();
194
195 // Runs the callbacks for any completed tasks, and starts work on the next.
196 void StartTask();
197
198 // Sets |flag| bit in |status_| to 0 and 1 respectively.
199 void ClearFlag(StatusFlag flag) { status_ &= ~flag; }
200 void SetFlag(StatusFlag flag) { status_ |= flag; }
201
202 // Returns true if the current status has the |flag| bit set to 1.
203 bool HasFlag(StatusFlag flag) const { return (status_ & flag) != 0; }
204
205 // Fetches the next required resource.
206 void FetchResource();
207
208 // Data retrieval methods.
209 void FetchManifest();
210 void OnDidGetManifest(const GURL& manifest_url,
211 const content::Manifest& manifest);
212
213 void CheckValidWebappManifest();
214
215 void CheckServiceWorker();
216 void OnDidCheckHasServiceWorker(bool has_service_worker);
217
218 void ExtractAndFetchBestIcon();
219 void OnAppIconFetched(const GURL icon_url, const SkBitmap& bitmap);
220
221 // content::WebContentsObserver overrides
222 void DidFinishNavigation(content::NavigationHandle* handle) override;
223 void WebContentsDestroyed() override;
224
225 // Internal status field to keep track of what resources have been retrieved.
226 uint32_t status_;
227
228 // Error codes for each resource retrieval operation.
229 ErrorCode processing_error_;
230 ErrorCode manifest_error_;
231 ErrorCode valid_webapp_manifest_error_;
232 ErrorCode service_worker_error_;
233 ErrorCode icon_error_;
234
235 // The list of params + callback pairs that have come from a call to Start.
236 std::vector<Task> tasks_;
237
238 // Tasks received while we are currently working. These are held separately to
239 // avoid contaminating the tasks_ vector (e.g. if a new Task is received
240 // during RunCallbacks, e.g. an InstallableCallback is invoked which calls
241 // Start), we cannot add it to tasks_ as the vector may be modified).
242 std::vector<Task> pending_tasks_;
243
244 // The icon size parameters used if a valid icon was requested.
245 int ideal_icon_size_in_dp_;
246 int minimum_icon_size_in_dp_;
247
248 // Installable properties cached on this object.
249 GURL manifest_url_;
250 content::Manifest manifest_;
251 GURL icon_url_;
252 std::unique_ptr<SkBitmap> icon_;
253 bool has_valid_webapp_manifest_;
254 bool has_service_worker_;
255
256 // This object has a lifetime scoped to a WebContents, so WeakPtrs can be used
257 // for binding callbacks.
258 base::WeakPtrFactory<InstallableChecker> weak_factory_;
259
260 DISALLOW_COPY_AND_ASSIGN(InstallableChecker);
261 };
262
263 } // namespace installable
264
265 #endif // CHROME_BROWSER_INSTALLABLE_INSTALLABLE_CHECKER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698