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

Side by Side Diff: ios/chrome/browser/reading_list/reading_list_entry.cc

Issue 2514333003: Componentize Reading List (Closed)
Patch Set: rebase Created 4 years, 1 month 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 #include "ios/chrome/browser/reading_list/reading_list_entry.h"
6
7 #include "base/json/json_string_value_serializer.h"
8 #include "base/memory/ptr_util.h"
9 #include "components/sync/protocol/reading_list_specifics.pb.h"
10 #include "ios/chrome/browser/reading_list/offline_url_utils.h"
11 #include "ios/chrome/browser/reading_list/proto/reading_list.pb.h"
12 #include "net/base/backoff_entry_serializer.h"
13
14 // The backoff time is the following: 10min, 10min, 1h, 2h, 2h..., starting
15 // after the first failure.
16 const net::BackoffEntry::Policy ReadingListEntry::kBackoffPolicy = {
17 // Number of initial errors (in sequence) to ignore before applying
18 // exponential back-off rules.
19 2,
20
21 // Initial delay for exponential back-off in ms.
22 10 * 60 * 1000, // 10 minutes.
23
24 // Factor by which the waiting time will be multiplied.
25 6,
26
27 // Fuzzing percentage. ex: 10% will spread requests randomly
28 // between 90%-100% of the calculated time.
29 0.1, // 10%.
30
31 // Maximum amount of time we are willing to delay our request in ms.
32 2 * 3600 * 1000, // 2 hours.
33
34 // Time to keep an entry from being discarded even when it
35 // has no significant state, -1 to never discard.
36 -1,
37
38 true, // Don't use initial delay unless the last request was an error.
39 };
40
41 ReadingListEntry::ReadingListEntry(const GURL& url, const std::string& title)
42 : ReadingListEntry(url, title, nullptr){};
43
44 ReadingListEntry::ReadingListEntry(const GURL& url,
45 const std::string& title,
46 std::unique_ptr<net::BackoffEntry> backoff)
47 : ReadingListEntry(url,
48 title,
49 0,
50 0,
51 WAITING,
52 base::FilePath(),
53 0,
54 std::move(backoff)) {}
55
56 ReadingListEntry::ReadingListEntry(
57 const GURL& url,
58 const std::string& title,
59 int64_t creation_time,
60 int64_t update_time,
61 ReadingListEntry::DistillationState distilled_state,
62 const base::FilePath& distilled_path,
63 int failed_download_counter,
64 std::unique_ptr<net::BackoffEntry> backoff)
65 : url_(url),
66 title_(title),
67 distilled_path_(distilled_path),
68 distilled_state_(distilled_state),
69 failed_download_counter_(failed_download_counter),
70 creation_time_us_(creation_time),
71 update_time_us_(update_time) {
72 if (backoff) {
73 backoff_ = std::move(backoff);
74 } else {
75 backoff_ = base::MakeUnique<net::BackoffEntry>(&kBackoffPolicy);
76 }
77 if (creation_time_us_ == 0) {
78 DCHECK(update_time_us_ == 0);
79 creation_time_us_ =
80 (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds();
81 update_time_us_ = creation_time_us_;
82 }
83 DCHECK(!url.is_empty());
84 DCHECK(url.is_valid());
85 }
86
87 ReadingListEntry::ReadingListEntry(ReadingListEntry&& entry)
88 : url_(std::move(entry.url_)),
89 title_(std::move(entry.title_)),
90 distilled_path_(std::move(entry.distilled_path_)),
91 distilled_state_(std::move(entry.distilled_state_)),
92 backoff_(std::move(entry.backoff_)),
93 failed_download_counter_(std::move(entry.failed_download_counter_)),
94 creation_time_us_(std::move(entry.creation_time_us_)),
95 update_time_us_(std::move(entry.update_time_us_)) {}
96
97 ReadingListEntry::~ReadingListEntry() {}
98
99 const GURL& ReadingListEntry::URL() const {
100 return url_;
101 }
102
103 const std::string& ReadingListEntry::Title() const {
104 return title_;
105 }
106
107 ReadingListEntry::DistillationState ReadingListEntry::DistilledState() const {
108 return distilled_state_;
109 }
110
111 const base::FilePath& ReadingListEntry::DistilledPath() const {
112 return distilled_path_;
113 }
114
115 const GURL ReadingListEntry::DistilledURL() const {
116 return reading_list::DistilledURLForPath(distilled_path_);
117 }
118
119 base::TimeDelta ReadingListEntry::TimeUntilNextTry() const {
120 return backoff_->GetTimeUntilRelease();
121 }
122
123 int ReadingListEntry::FailedDownloadCounter() const {
124 return failed_download_counter_;
125 }
126
127 ReadingListEntry& ReadingListEntry::operator=(ReadingListEntry&& other) {
128 url_ = std::move(other.url_);
129 title_ = std::move(other.title_);
130 distilled_path_ = std::move(other.distilled_path_);
131 distilled_state_ = std::move(other.distilled_state_);
132 backoff_ = std::move(other.backoff_);
133 failed_download_counter_ = std::move(other.failed_download_counter_);
134 creation_time_us_ = std::move(other.creation_time_us_);
135 update_time_us_ = std::move(other.update_time_us_);
136 return *this;
137 }
138
139 bool ReadingListEntry::operator==(const ReadingListEntry& other) const {
140 return url_ == other.url_;
141 }
142
143 void ReadingListEntry::SetTitle(const std::string& title) {
144 title_ = title;
145 }
146
147 void ReadingListEntry::SetDistilledPath(const base::FilePath& path) {
148 DCHECK(!path.empty());
149 distilled_path_ = path;
150 distilled_state_ = PROCESSED;
151 backoff_->Reset();
152 failed_download_counter_ = 0;
153 }
154
155 void ReadingListEntry::SetDistilledState(DistillationState distilled_state) {
156 DCHECK(distilled_state != PROCESSED); // use SetDistilledPath instead.
157 DCHECK(distilled_state != WAITING);
158 // Increase time until next retry exponentially if the state change from a
159 // non-error state to an error state.
160 if ((distilled_state == WILL_RETRY || distilled_state == ERROR) &&
161 distilled_state_ != WILL_RETRY && distilled_state_ != ERROR) {
162 backoff_->InformOfRequest(false);
163 failed_download_counter_++;
164 }
165
166 distilled_state_ = distilled_state;
167 distilled_path_ = base::FilePath();
168 }
169
170 int64_t ReadingListEntry::UpdateTime() const {
171 return update_time_us_;
172 }
173
174 int64_t ReadingListEntry::CreationTime() const {
175 return creation_time_us_;
176 }
177
178 void ReadingListEntry::MarkEntryUpdated() {
179 update_time_us_ =
180 (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds();
181 }
182
183 // static
184 std::unique_ptr<ReadingListEntry> ReadingListEntry::FromReadingListLocal(
185 const reading_list::ReadingListLocal& pb_entry) {
186 if (!pb_entry.has_url()) {
187 return nullptr;
188 }
189 GURL url(pb_entry.url());
190 if (url.is_empty() || !url.is_valid()) {
191 return nullptr;
192 }
193 std::string title;
194 if (pb_entry.has_title()) {
195 title = pb_entry.title();
196 }
197
198 int64_t creation_time_us = 0;
199 if (pb_entry.has_creation_time_us()) {
200 creation_time_us = pb_entry.creation_time_us();
201 }
202
203 int64_t update_time_us = 0;
204 if (pb_entry.has_update_time_us()) {
205 update_time_us = pb_entry.update_time_us();
206 }
207
208 ReadingListEntry::DistillationState distillation_state =
209 ReadingListEntry::WAITING;
210 if (pb_entry.has_distillation_state()) {
211 switch (pb_entry.distillation_state()) {
212 case reading_list::ReadingListLocal::WAITING:
213 distillation_state = ReadingListEntry::WAITING;
214 break;
215 case reading_list::ReadingListLocal::PROCESSING:
216 distillation_state = ReadingListEntry::PROCESSING;
217 break;
218 case reading_list::ReadingListLocal::PROCESSED:
219 distillation_state = ReadingListEntry::PROCESSED;
220 break;
221 case reading_list::ReadingListLocal::WILL_RETRY:
222 distillation_state = ReadingListEntry::WILL_RETRY;
223 break;
224 case reading_list::ReadingListLocal::ERROR:
225 distillation_state = ReadingListEntry::ERROR;
226 break;
227 }
228 }
229
230 base::FilePath distilled_path;
231 if (pb_entry.has_distilled_path()) {
232 distilled_path = base::FilePath(pb_entry.distilled_path());
233 }
234
235 int64_t failed_download_counter = 0;
236 if (pb_entry.has_failed_download_counter()) {
237 failed_download_counter = pb_entry.failed_download_counter();
238 }
239
240 std::unique_ptr<net::BackoffEntry> backoff;
241 if (pb_entry.has_backoff()) {
242 JSONStringValueDeserializer deserializer(pb_entry.backoff());
243 std::unique_ptr<base::Value> value(
244 deserializer.Deserialize(nullptr, nullptr));
245 if (value) {
246 backoff = net::BackoffEntrySerializer::DeserializeFromValue(
247 *value, &kBackoffPolicy, nullptr, base::Time::Now());
248 }
249 }
250
251 return base::WrapUnique<ReadingListEntry>(new ReadingListEntry(
252 url, title, creation_time_us, update_time_us, distillation_state,
253 distilled_path, failed_download_counter, std::move(backoff)));
254 }
255
256 // static
257 std::unique_ptr<ReadingListEntry> ReadingListEntry::FromReadingListSpecifics(
258 const sync_pb::ReadingListSpecifics& pb_entry) {
259 if (!pb_entry.has_url()) {
260 return nullptr;
261 }
262 GURL url(pb_entry.url());
263 if (url.is_empty() || !url.is_valid()) {
264 return nullptr;
265 }
266 std::string title;
267 if (pb_entry.has_title()) {
268 title = pb_entry.title();
269 }
270
271 int64_t creation_time_us = 0;
272 if (pb_entry.has_creation_time_us()) {
273 creation_time_us = pb_entry.creation_time_us();
274 }
275
276 int64_t update_time_us = 0;
277 if (pb_entry.has_update_time_us()) {
278 update_time_us = pb_entry.update_time_us();
279 }
280
281 return base::WrapUnique<ReadingListEntry>(
282 new ReadingListEntry(url, title, creation_time_us, update_time_us,
283 WAITING, base::FilePath(), 0, nullptr));
284 }
285
286 void ReadingListEntry::MergeLocalStateFrom(ReadingListEntry& other) {
287 distilled_path_ = std::move(other.distilled_path_);
288 distilled_state_ = std::move(other.distilled_state_);
289 backoff_ = std::move(other.backoff_);
290 failed_download_counter_ = std::move(other.failed_download_counter_);
291 }
292
293 std::unique_ptr<reading_list::ReadingListLocal>
294 ReadingListEntry::AsReadingListLocal(bool read) const {
295 std::unique_ptr<reading_list::ReadingListLocal> pb_entry =
296 base::MakeUnique<reading_list::ReadingListLocal>();
297
298 // URL is used as the key for the database and sync as there is only one entry
299 // per URL.
300 pb_entry->set_entry_id(URL().spec());
301 pb_entry->set_title(Title());
302 pb_entry->set_url(URL().spec());
303 pb_entry->set_creation_time_us(CreationTime());
304 pb_entry->set_update_time_us(UpdateTime());
305
306 if (read) {
307 pb_entry->set_status(reading_list::ReadingListLocal::READ);
308 } else {
309 pb_entry->set_status(reading_list::ReadingListLocal::UNREAD);
310 }
311
312 reading_list::ReadingListLocal::DistillationState distilation_state;
313 switch (DistilledState()) {
314 case ReadingListEntry::WAITING:
315 distilation_state = reading_list::ReadingListLocal::WAITING;
316 break;
317 case ReadingListEntry::PROCESSING:
318 distilation_state = reading_list::ReadingListLocal::PROCESSING;
319 break;
320 case ReadingListEntry::PROCESSED:
321 distilation_state = reading_list::ReadingListLocal::PROCESSED;
322 break;
323 case ReadingListEntry::WILL_RETRY:
324 distilation_state = reading_list::ReadingListLocal::WILL_RETRY;
325 break;
326 case ReadingListEntry::ERROR:
327 distilation_state = reading_list::ReadingListLocal::ERROR;
328 break;
329 }
330 pb_entry->set_distillation_state(distilation_state);
331 if (!DistilledPath().empty()) {
332 pb_entry->set_distilled_path(DistilledPath().value());
333 }
334 pb_entry->set_failed_download_counter(failed_download_counter_);
335
336 if (backoff_) {
337 std::unique_ptr<base::Value> backoff =
338 net::BackoffEntrySerializer::SerializeToValue(*backoff_,
339 base::Time::Now());
340
341 std::string output;
342 JSONStringValueSerializer serializer(&output);
343 serializer.Serialize(*backoff);
344 pb_entry->set_backoff(output);
345 }
346 return pb_entry;
347 }
348
349 std::unique_ptr<sync_pb::ReadingListSpecifics>
350 ReadingListEntry::AsReadingListSpecifics(bool read) const {
351 std::unique_ptr<sync_pb::ReadingListSpecifics> pb_entry =
352 base::MakeUnique<sync_pb::ReadingListSpecifics>();
353
354 // URL is used as the key for the database and sync as there is only one entry
355 // per URL.
356 pb_entry->set_entry_id(URL().spec());
357 pb_entry->set_title(Title());
358 pb_entry->set_url(URL().spec());
359 pb_entry->set_creation_time_us(CreationTime());
360 pb_entry->set_update_time_us(UpdateTime());
361
362 if (read) {
363 pb_entry->set_status(sync_pb::ReadingListSpecifics::READ);
364 } else {
365 pb_entry->set_status(sync_pb::ReadingListSpecifics::UNREAD);
366 }
367
368 return pb_entry;
369 }
370
371 bool ReadingListEntry::CompareEntryUpdateTime(const ReadingListEntry& lhs,
372 const ReadingListEntry& rhs) {
373 return lhs.UpdateTime() > rhs.UpdateTime();
374 }
OLDNEW
« no previous file with comments | « ios/chrome/browser/reading_list/reading_list_entry.h ('k') | ios/chrome/browser/reading_list/reading_list_entry_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698