1 // Copyright 2017 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 COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_TYPES_H_
6 #define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_TYPES_H_
7 
8 #include <array>
9 #include <string>
10 #include <vector>
11 
12 #include "base/callback.h"
13 #include "base/files/file_path.h"
14 #include "base/optional.h"
15 #include "base/strings/string16.h"
16 #include "base/time/time.h"
17 #include "components/offline_pages/core/client_id.h"
18 #include "url/gurl.h"
19 
20 namespace offline_pages {
21 
22 // Controls how to reschedule a background task.
23 // A Java counterpart will be generated for this enum.
24 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.offlinepages
25 enum class PrefetchBackgroundTaskRescheduleType {
26   // No reschedule.
27   NO_RESCHEDULE,
28   // Reschedules the task in the next available WiFi window after 15 minutes
29   // have passed.
30   RESCHEDULE_WITHOUT_BACKOFF,
31   // Reschedules the task with backoff included.
32   RESCHEDULE_WITH_BACKOFF,
33   // Reschedules the task due to the fact that it is killed due to the system
34   // constraint.
35   RESCHEDULE_DUE_TO_SYSTEM,
36   // Reschedules the task after 1 day.
37   SUSPEND
38 };
39 
40 // Status for sending prefetch request to the server. This has a matching type
41 // in enums.xml which must be adjusted if we add any new values here.
42 enum class PrefetchRequestStatus {
43   // Request completed successfully.
44   kSuccess = 0,
45   // Request failed due to to local network problem, unrelated to server load
46   // levels. The caller will simply reschedule the retry in the next available
47   // WiFi window after 15 minutes have passed.
48   kShouldRetryWithoutBackoff = 1,
49   // Request failed probably related to transient server problems. The caller
50   // will reschedule the retry with backoff included.
51   kShouldRetryWithBackoff = 2,
52   // Request failed with error indicating that the server no longer knows how
53   // to service a request. The caller will prevent network requests for the
54   // period of 1 day.
55   kShouldSuspendNotImplemented = 3,
56   // Request failed with error indicating that the client is forbidden. The
57   // caller will prevent network requests for the period of 1 day.
58   kShouldSuspendForbidden = 4,
59   // The request failed because the service URL was blocked by the domain
60   // administrator.
61   kShouldSuspendBlockedByAdministrator = 5,
62   // The request was answered with a 403 Forbidden response including a message
63   // indicating that the request was forbidden specifically by an OPS request
64   // filtering rule.
65   kShouldSuspendForbiddenByOPS = 6,
66   // The server responded with 403 forbidden due to a filter rule though the
67   // last request was successful.
68   kShouldSuspendNewlyForbiddenByOPS = 7,
69   // A request for no URLs (i.e. server-enabled check) completed successfully.
70   kEmptyRequestSuccess = 8,
71   // kMaxValue should always be the last type.
72   kMaxValue = kEmptyRequestSuccess
73 };
74 
75 // Status indicating the page rendering status in the server.
76 enum class RenderStatus {
77   // The page is rendered.
78   RENDERED,
79   // The page is still being processed.
80   PENDING,
81   // The page failed to render.
82   FAILED,
83   // Failed due to bundle size limits.
84   EXCEEDED_LIMIT
85 };
86 
87 // Information about the page rendered in the server.
88 struct RenderPageInfo {
89   RenderPageInfo();
90   RenderPageInfo(const RenderPageInfo& other);
91 
92   // The URL of the page that was rendered.
93   std::string url;
94   // The final URL after redirects. Empty if the final URL is url.
95   std::string redirect_url;
96   // Status of the render attempt.
97   RenderStatus status = RenderStatus::FAILED;
98   // Resource name for the body which can be read via the ByteStream API.
99   // Set only when |status| is RENDERED.
100   std::string body_name;
101   // Length of the body in bytes. Set only when |status| is RENDERED.
102   int64_t body_length = 0LL;
103   // Time the page was rendered. Set only when |status| is RENDERED.
104   base::Time render_time;
105 };
106 
107 // Contains all states an item can be at during its progress through the
108 // prefetching pipeline. State progression will normally follow the order below,
109 // but some states might be skipped and there might be backtracking when
110 // retrying a failed operation.
111 //
112 // Changes to this enum must be reflected in the respective metrics enum named
113 // OfflinePrefetchItemState in enums.xml. Use the exact same integer value for
114 // each mirrored entry. Existing elements should never have their assigned
115 // values changed. Changes should also be reflected in
116 // |PrefetchTaskTestBase::kOrderedPrefetchItemStates|.
117 enum class PrefetchItemState : int {
118   // New request just received from the client.
119   NEW_REQUEST = 0,
120   // The item has been included in a GeneratePageBundle RPC requesting the
121   // creation of an archive for its URL.
122   SENT_GENERATE_PAGE_BUNDLE = 10,
123   // The archive was not immediately available (cached) upon the request and
124   // is now waiting for a GCM message notifying of its archiving operation
125   // completion.
126   AWAITING_GCM = 20,
127   // The GCM message notifying of the archiving operation completion was
128   // received for this item.
129   RECEIVED_GCM = 30,
130   // A GetOperation RPC was sent for this item to query for the final results
131   // of its archiving request.
132   SENT_GET_OPERATION = 40,
133   // Information was received about a successfully created archive for this
134   // item that can now be downloaded.
135   RECEIVED_BUNDLE = 50,
136   // This item's archive is currently being downloaded.
137   DOWNLOADING = 60,
138   // The archive has been downloaded, waiting to be imported into offline pages
139   // model.
140   DOWNLOADED = 70,
141   // The archive is being imported into offline pages model.
142   IMPORTING = 80,
143   // Item has finished processing, successfully or otherwise, and is waiting to
144   // be processed for stats reporting to UMA.
145   FINISHED = 90,
146   // UMA stats have been reported and the item is being kept just long enough
147   // to confirm that the same URL is not being repeatedly requested by its
148   // client.
149   ZOMBIE = 100,
150   // Max item state, needed for histograms
151   kMaxValue = ZOMBIE
152 };
153 
154 base::Optional<PrefetchItemState> ToPrefetchItemState(int value);
155 
156 // Error codes used to identify the reason why a prefetch entry has finished
157 // processing in the pipeline. This values are only meaningful for entries in
158 // the "finished" state.
159 //
160 // New entries can be added anywhere as long as they are assigned unique values
161 // and kept in ascending order. Deprecated entries should be labeled as such but
162 // never removed. Assigned values should never be reused. Remember to update the
163 // kMaxValue value if adding a new trailing item.
164 //
165 // Changes to this enum must be reflected in the respective metrics enum named
166 // OflinePrefetchItemErrorCode in enums.xml. Use the exact same integer value
167 // for each mirrored entry.
168 enum class PrefetchItemErrorCode : int {
169   // The entry had gone through the pipeline and successfully completed
170   // prefetching. Explicitly setting to 0 as that is the default value for the
171   // respective SQLite column.
172   SUCCESS = 0,
173   // Got too many URLs from suggestions, canceled this one. See kMaxUrlsToSend
174   // defined in GeneratePageBundleTask.
175   TOO_MANY_NEW_URLS = 100,
176   // An error happened while attempting to download the archive file.
177   DOWNLOAD_ERROR = 200,
178   // An error happened while importing the downloaded archive file int the
179   // Offline Pages system.
180   IMPORT_ERROR = 300,
181   // Got a failure result from GetOperation (or the GeneratePageBundle
182   // metadata).
183   ARCHIVING_FAILED = 400,
184   // Got a failure result from GetOperation or GeneratePageBundle that a
185   // server-side limit on the page was exceeded.
186   ARCHIVING_LIMIT_EXCEEDED = 500,
187   // These next STALE_AT_* values identify entries that stayed for too long in
188   // the same pipeline bucket so that their "freshness date" was considered too
189   // old for what was allowed for that bucket. See StaleEntryFinalizerTask for
190   // more details.
191   STALE_AT_NEW_REQUEST = 600,
192   STALE_AT_AWAITING_GCM = 700,
193   STALE_AT_RECEIVED_GCM = 800,
194   STALE_AT_RECEIVED_BUNDLE = 900,
195   STALE_AT_DOWNLOADING = 1000,
196   STALE_AT_IMPORTING = 1050,
197   STALE_AT_UNKNOWN = 1100,
198   // The item was terminated because it remained in the pipeline for more than
199   // 7 days.
200   STUCK = 1150,
201   // The item had some invalid data, probably due to database corruption.
202   INVALID_ITEM = 1175,
203   // Exceeded maximum retries for get operation request.
204   GET_OPERATION_MAX_ATTEMPTS_REACHED = 1200,
205   // Exceeded maximum retries limit for generate page bundle request.
206   GENERATE_PAGE_BUNDLE_REQUEST_MAX_ATTEMPTS_REACHED = 1300,
207   // Exceeded maximum retries for download.
208   DOWNLOAD_MAX_ATTEMPTS_REACHED = 1400,
209   // Clock was set back too far in time.
210   MAXIMUM_CLOCK_BACKWARD_SKEW_EXCEEDED = 1500,
211   // The archive importing was not completed probably due to that Chrome was
212   // killed before everything finishes.
213   IMPORT_LOST = 1600,
214   // The page suggestion is no longer valid, so the item no longer needs to be
215   // downloaded.
216   SUGGESTION_INVALIDATED = 1700,
217   // Note: Must always have the same value as the last actual entry.
218   kMaxValue = SUGGESTION_INVALIDATED
219 };
220 
221 base::Optional<PrefetchItemErrorCode> ToPrefetchItemErrorCode(int value);
222 
223 // Callback invoked upon completion of a prefetch request.
224 using PrefetchRequestFinishedCallback =
225     base::OnceCallback<void(PrefetchRequestStatus status,
226                             const std::string& operation_name,
227                             const std::vector<RenderPageInfo>& pages)>;
228 
229 // Holds information about a suggested URL to be prefetched.
230 struct PrefetchURL {
231   PrefetchURL(const std::string& id,
232               const GURL& url,
233               const base::string16& title);
234   PrefetchURL(const std::string& id,
235               const GURL& url,
236               const base::string16& title,
237               const GURL& thumbnail_url,
238               const GURL& favicon_url,
239               const std::string& snippet,
240               const std::string& attribution);
241   ~PrefetchURL();
242   PrefetchURL(const PrefetchURL& other);
243 
244   // Client provided ID to allow the matching of provided URLs to the respective
245   // work item in the prefetching system within that client's assigned
246   // namespace. It can be any string value and it will not be used internally
247   // for de-duplication.
248   std::string id;
249 
250   // This URL will be prefetched by the service.
251   GURL url;
252 
253   // The title of the page.
254   base::string16 title;
255 
256   // URL for a thumbnail that represents the page. May be empty if no thumbnail
257   // is available.
258   GURL thumbnail_url;
259 
260   // URL for page's favicon.
261   GURL favicon_url;
262 
263   // Article snippet.
264   std::string snippet;
265 
266   // Identifies the page's publisher.
267   std::string attribution;
268 };
269 
270 // Result of a completed download.
271 struct PrefetchDownloadResult {
272   PrefetchDownloadResult();
273   PrefetchDownloadResult(const std::string& download_id,
274                          const base::FilePath& file_path,
275                          int64_t file_size);
276   PrefetchDownloadResult(const PrefetchDownloadResult& other);
277   bool operator==(const PrefetchDownloadResult& other) const;
278 
279   std::string download_id;
280   bool success = false;
281   base::FilePath file_path;
282   int64_t file_size = 0;
283 };
284 
285 // Describes all the info needed to import an archive.
286 struct PrefetchArchiveInfo {
287   PrefetchArchiveInfo();
288   PrefetchArchiveInfo(const PrefetchArchiveInfo& other);
289   ~PrefetchArchiveInfo();
290   bool empty() const;
291 
292   int64_t offline_id = 0;  // Defaults to invalid id.
293   ClientId client_id;
294   GURL url;
295   GURL final_archived_url;
296   base::string16 title;
297   base::FilePath file_path;
298   int64_t file_size = 0;
299   GURL favicon_url;
300   std::string snippet;
301   std::string attribution;
302 };
303 
304 // These operators are implemented for testing only, see test_util.cc.
305 // They are provided here to avoid ODR problems.
306 std::ostream& operator<<(std::ostream& out,
307                          PrefetchBackgroundTaskRescheduleType value);
308 std::ostream& operator<<(std::ostream& out, PrefetchRequestStatus value);
309 std::ostream& operator<<(std::ostream& out, RenderStatus value);
310 std::ostream& operator<<(std::ostream& out, const PrefetchItemState& value);
311 std::ostream& operator<<(std::ostream& out, PrefetchItemErrorCode value);
312 
313 }  // namespace offline_pages
314 
315 #endif  // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_TYPES_H_
316