OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/reading_list/ios/reading_list_entry.h" | 5 #include "components/reading_list/ios/reading_list_entry.h" |
6 | 6 |
7 #include "base/json/json_string_value_serializer.h" | 7 #include "base/json/json_string_value_serializer.h" |
8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
9 #include "components/reading_list/ios/offline_url_utils.h" | 9 #include "components/reading_list/ios/offline_url_utils.h" |
10 #include "components/reading_list/ios/proto/reading_list.pb.h" | 10 #include "components/reading_list/ios/proto/reading_list.pb.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
44 | 44 |
45 ReadingListEntry::ReadingListEntry(const GURL& url, | 45 ReadingListEntry::ReadingListEntry(const GURL& url, |
46 const std::string& title, | 46 const std::string& title, |
47 std::unique_ptr<net::BackoffEntry> backoff) | 47 std::unique_ptr<net::BackoffEntry> backoff) |
48 : ReadingListEntry(url, | 48 : ReadingListEntry(url, |
49 title, | 49 title, |
50 UNSEEN, | 50 UNSEEN, |
51 0, | 51 0, |
52 0, | 52 0, |
53 0, | 53 0, |
54 0, | |
54 WAITING, | 55 WAITING, |
55 base::FilePath(), | 56 base::FilePath(), |
56 0, | 57 0, |
57 std::move(backoff)) {} | 58 std::move(backoff)) {} |
58 | 59 |
59 ReadingListEntry::ReadingListEntry( | 60 ReadingListEntry::ReadingListEntry( |
60 const GURL& url, | 61 const GURL& url, |
61 const std::string& title, | 62 const std::string& title, |
62 State state, | 63 State state, |
63 int64_t creation_time, | 64 int64_t creation_time, |
64 int64_t first_read_time, | 65 int64_t first_read_time, |
65 int64_t update_time, | 66 int64_t update_time, |
67 int64_t update_title_time, | |
66 ReadingListEntry::DistillationState distilled_state, | 68 ReadingListEntry::DistillationState distilled_state, |
67 const base::FilePath& distilled_path, | 69 const base::FilePath& distilled_path, |
68 int failed_download_counter, | 70 int failed_download_counter, |
69 std::unique_ptr<net::BackoffEntry> backoff) | 71 std::unique_ptr<net::BackoffEntry> backoff) |
70 : url_(url), | 72 : url_(url), |
71 title_(title), | 73 title_(title), |
72 state_(state), | 74 state_(state), |
73 distilled_path_(distilled_path), | 75 distilled_path_(distilled_path), |
74 distilled_state_(distilled_state), | 76 distilled_state_(distilled_state), |
75 failed_download_counter_(failed_download_counter), | 77 failed_download_counter_(failed_download_counter), |
76 creation_time_us_(creation_time), | 78 creation_time_us_(creation_time), |
77 first_read_time_us_(first_read_time), | 79 first_read_time_us_(first_read_time), |
78 update_time_us_(update_time) { | 80 update_time_us_(update_time), |
81 update_title_time_us_(update_title_time) { | |
79 if (backoff) { | 82 if (backoff) { |
80 backoff_ = std::move(backoff); | 83 backoff_ = std::move(backoff); |
81 } else { | 84 } else { |
82 backoff_ = base::MakeUnique<net::BackoffEntry>(&kBackoffPolicy); | 85 backoff_ = base::MakeUnique<net::BackoffEntry>(&kBackoffPolicy); |
83 } | 86 } |
84 if (creation_time_us_ == 0) { | 87 if (creation_time_us_ == 0) { |
85 DCHECK(update_time_us_ == 0); | 88 DCHECK(update_time_us_ == 0); |
89 DCHECK(update_title_time_us_ == 0); | |
86 creation_time_us_ = | 90 creation_time_us_ = |
87 (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds(); | 91 (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds(); |
88 update_time_us_ = creation_time_us_; | 92 update_time_us_ = creation_time_us_; |
93 update_title_time_us_ = creation_time_us_; | |
89 } | 94 } |
90 DCHECK(!url.is_empty()); | 95 DCHECK(!url.is_empty()); |
91 DCHECK(url.is_valid()); | 96 DCHECK(url.is_valid()); |
92 } | 97 } |
93 | 98 |
94 ReadingListEntry::ReadingListEntry(ReadingListEntry&& entry) | 99 ReadingListEntry::ReadingListEntry(ReadingListEntry&& entry) |
95 : url_(std::move(entry.url_)), | 100 : url_(std::move(entry.url_)), |
96 title_(std::move(entry.title_)), | 101 title_(std::move(entry.title_)), |
97 state_(std::move(entry.state_)), | 102 state_(std::move(entry.state_)), |
98 distilled_path_(std::move(entry.distilled_path_)), | 103 distilled_path_(std::move(entry.distilled_path_)), |
99 distilled_state_(std::move(entry.distilled_state_)), | 104 distilled_state_(std::move(entry.distilled_state_)), |
100 backoff_(std::move(entry.backoff_)), | 105 backoff_(std::move(entry.backoff_)), |
101 failed_download_counter_(std::move(entry.failed_download_counter_)), | 106 failed_download_counter_(std::move(entry.failed_download_counter_)), |
102 creation_time_us_(std::move(entry.creation_time_us_)), | 107 creation_time_us_(std::move(entry.creation_time_us_)), |
103 first_read_time_us_(std::move(entry.first_read_time_us_)), | 108 first_read_time_us_(std::move(entry.first_read_time_us_)), |
104 update_time_us_(std::move(entry.update_time_us_)) {} | 109 update_time_us_(std::move(entry.update_time_us_)), |
110 update_title_time_us_(std::move(entry.update_title_time_us_)) {} | |
105 | 111 |
106 ReadingListEntry::~ReadingListEntry() {} | 112 ReadingListEntry::~ReadingListEntry() {} |
107 | 113 |
108 const GURL& ReadingListEntry::URL() const { | 114 const GURL& ReadingListEntry::URL() const { |
109 return url_; | 115 return url_; |
110 } | 116 } |
111 | 117 |
112 const std::string& ReadingListEntry::Title() const { | 118 const std::string& ReadingListEntry::Title() const { |
113 return title_; | 119 return title_; |
114 } | 120 } |
(...skipping 18 matching lines...) Expand all Loading... | |
133 url_ = std::move(other.url_); | 139 url_ = std::move(other.url_); |
134 title_ = std::move(other.title_); | 140 title_ = std::move(other.title_); |
135 distilled_path_ = std::move(other.distilled_path_); | 141 distilled_path_ = std::move(other.distilled_path_); |
136 distilled_state_ = std::move(other.distilled_state_); | 142 distilled_state_ = std::move(other.distilled_state_); |
137 backoff_ = std::move(other.backoff_); | 143 backoff_ = std::move(other.backoff_); |
138 state_ = std::move(other.state_); | 144 state_ = std::move(other.state_); |
139 failed_download_counter_ = std::move(other.failed_download_counter_); | 145 failed_download_counter_ = std::move(other.failed_download_counter_); |
140 creation_time_us_ = std::move(other.creation_time_us_); | 146 creation_time_us_ = std::move(other.creation_time_us_); |
141 first_read_time_us_ = std::move(other.first_read_time_us_); | 147 first_read_time_us_ = std::move(other.first_read_time_us_); |
142 update_time_us_ = std::move(other.update_time_us_); | 148 update_time_us_ = std::move(other.update_time_us_); |
149 update_title_time_us_ = std::move(other.update_title_time_us_); | |
143 return *this; | 150 return *this; |
144 } | 151 } |
145 | 152 |
146 bool ReadingListEntry::operator==(const ReadingListEntry& other) const { | 153 bool ReadingListEntry::operator==(const ReadingListEntry& other) const { |
147 return url_ == other.url_; | 154 return url_ == other.url_; |
148 } | 155 } |
149 | 156 |
150 void ReadingListEntry::SetTitle(const std::string& title) { | 157 void ReadingListEntry::SetTitle(const std::string& title) { |
151 title_ = title; | 158 title_ = title; |
159 update_title_time_us_ = | |
160 (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds(); | |
152 } | 161 } |
153 | 162 |
154 void ReadingListEntry::SetRead(bool read) { | 163 void ReadingListEntry::SetRead(bool read) { |
155 state_ = read ? READ : UNREAD; | 164 state_ = read ? READ : UNREAD; |
156 if (FirstReadTime() == 0 && read) { | 165 if (FirstReadTime() == 0 && read) { |
157 first_read_time_us_ = | 166 first_read_time_us_ = |
158 (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds(); | 167 (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds(); |
159 } | 168 } |
160 MarkEntryUpdated(); | 169 MarkEntryUpdated(); |
161 } | 170 } |
(...skipping 26 matching lines...) Expand all Loading... | |
188 } | 197 } |
189 | 198 |
190 distilled_state_ = distilled_state; | 199 distilled_state_ = distilled_state; |
191 distilled_path_ = base::FilePath(); | 200 distilled_path_ = base::FilePath(); |
192 } | 201 } |
193 | 202 |
194 int64_t ReadingListEntry::UpdateTime() const { | 203 int64_t ReadingListEntry::UpdateTime() const { |
195 return update_time_us_; | 204 return update_time_us_; |
196 } | 205 } |
197 | 206 |
207 int64_t ReadingListEntry::UpdateTitleTime() const { | |
208 return update_title_time_us_; | |
209 } | |
210 | |
198 int64_t ReadingListEntry::CreationTime() const { | 211 int64_t ReadingListEntry::CreationTime() const { |
199 return creation_time_us_; | 212 return creation_time_us_; |
200 } | 213 } |
201 | 214 |
202 int64_t ReadingListEntry::FirstReadTime() const { | 215 int64_t ReadingListEntry::FirstReadTime() const { |
203 return first_read_time_us_; | 216 return first_read_time_us_; |
204 } | 217 } |
205 | 218 |
206 void ReadingListEntry::MarkEntryUpdated() { | 219 void ReadingListEntry::MarkEntryUpdated() { |
207 update_time_us_ = | 220 update_time_us_ = |
(...skipping 23 matching lines...) Expand all Loading... | |
231 int64_t first_read_time_us = 0; | 244 int64_t first_read_time_us = 0; |
232 if (pb_entry.has_first_read_time_us()) { | 245 if (pb_entry.has_first_read_time_us()) { |
233 first_read_time_us = pb_entry.first_read_time_us(); | 246 first_read_time_us = pb_entry.first_read_time_us(); |
234 } | 247 } |
235 | 248 |
236 int64_t update_time_us = 0; | 249 int64_t update_time_us = 0; |
237 if (pb_entry.has_update_time_us()) { | 250 if (pb_entry.has_update_time_us()) { |
238 update_time_us = pb_entry.update_time_us(); | 251 update_time_us = pb_entry.update_time_us(); |
239 } | 252 } |
240 | 253 |
254 int64_t update_title_time_us = 0; | |
255 if (pb_entry.has_update_title_time_us()) { | |
256 update_title_time_us = pb_entry.update_title_time_us(); | |
257 } | |
258 | |
241 State state = UNSEEN; | 259 State state = UNSEEN; |
242 if (pb_entry.has_status()) { | 260 if (pb_entry.has_status()) { |
243 switch (pb_entry.status()) { | 261 switch (pb_entry.status()) { |
244 case reading_list::ReadingListLocal::READ: | 262 case reading_list::ReadingListLocal::READ: |
245 state = READ; | 263 state = READ; |
246 break; | 264 break; |
247 case reading_list::ReadingListLocal::UNREAD: | 265 case reading_list::ReadingListLocal::UNREAD: |
248 state = UNREAD; | 266 state = UNREAD; |
249 break; | 267 break; |
250 case reading_list::ReadingListLocal::UNSEEN: | 268 case reading_list::ReadingListLocal::UNSEEN: |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
291 std::unique_ptr<base::Value> value( | 309 std::unique_ptr<base::Value> value( |
292 deserializer.Deserialize(nullptr, nullptr)); | 310 deserializer.Deserialize(nullptr, nullptr)); |
293 if (value) { | 311 if (value) { |
294 backoff = net::BackoffEntrySerializer::DeserializeFromValue( | 312 backoff = net::BackoffEntrySerializer::DeserializeFromValue( |
295 *value, &kBackoffPolicy, nullptr, base::Time::Now()); | 313 *value, &kBackoffPolicy, nullptr, base::Time::Now()); |
296 } | 314 } |
297 } | 315 } |
298 | 316 |
299 return base::WrapUnique<ReadingListEntry>(new ReadingListEntry( | 317 return base::WrapUnique<ReadingListEntry>(new ReadingListEntry( |
300 url, title, state, creation_time_us, first_read_time_us, update_time_us, | 318 url, title, state, creation_time_us, first_read_time_us, update_time_us, |
301 distillation_state, distilled_path, failed_download_counter, | 319 update_title_time_us, distillation_state, distilled_path, |
302 std::move(backoff))); | 320 failed_download_counter, std::move(backoff))); |
303 } | 321 } |
304 | 322 |
305 // static | 323 // static |
306 std::unique_ptr<ReadingListEntry> ReadingListEntry::FromReadingListSpecifics( | 324 std::unique_ptr<ReadingListEntry> ReadingListEntry::FromReadingListSpecifics( |
307 const sync_pb::ReadingListSpecifics& pb_entry) { | 325 const sync_pb::ReadingListSpecifics& pb_entry) { |
308 if (!pb_entry.has_url()) { | 326 if (!pb_entry.has_url()) { |
309 return nullptr; | 327 return nullptr; |
310 } | 328 } |
311 GURL url(pb_entry.url()); | 329 GURL url(pb_entry.url()); |
312 if (url.is_empty() || !url.is_valid()) { | 330 if (url.is_empty() || !url.is_valid()) { |
(...skipping 12 matching lines...) Expand all Loading... | |
325 int64_t first_read_time_us = 0; | 343 int64_t first_read_time_us = 0; |
326 if (pb_entry.has_first_read_time_us()) { | 344 if (pb_entry.has_first_read_time_us()) { |
327 first_read_time_us = pb_entry.first_read_time_us(); | 345 first_read_time_us = pb_entry.first_read_time_us(); |
328 } | 346 } |
329 | 347 |
330 int64_t update_time_us = 0; | 348 int64_t update_time_us = 0; |
331 if (pb_entry.has_update_time_us()) { | 349 if (pb_entry.has_update_time_us()) { |
332 update_time_us = pb_entry.update_time_us(); | 350 update_time_us = pb_entry.update_time_us(); |
333 } | 351 } |
334 | 352 |
353 int64_t update_title_time_us = 0; | |
354 if (pb_entry.has_update_title_time_us()) { | |
355 update_title_time_us = pb_entry.update_title_time_us(); | |
356 } | |
357 | |
335 State state = UNSEEN; | 358 State state = UNSEEN; |
336 if (pb_entry.has_status()) { | 359 if (pb_entry.has_status()) { |
337 switch (pb_entry.status()) { | 360 switch (pb_entry.status()) { |
338 case sync_pb::ReadingListSpecifics::READ: | 361 case sync_pb::ReadingListSpecifics::READ: |
339 state = READ; | 362 state = READ; |
340 break; | 363 break; |
341 case sync_pb::ReadingListSpecifics::UNREAD: | 364 case sync_pb::ReadingListSpecifics::UNREAD: |
342 state = UNREAD; | 365 state = UNREAD; |
343 break; | 366 break; |
344 case sync_pb::ReadingListSpecifics::UNSEEN: | 367 case sync_pb::ReadingListSpecifics::UNSEEN: |
345 state = UNSEEN; | 368 state = UNSEEN; |
346 break; | 369 break; |
347 } | 370 } |
348 } | 371 } |
349 | 372 |
350 return base::WrapUnique<ReadingListEntry>(new ReadingListEntry( | 373 return base::WrapUnique<ReadingListEntry>(new ReadingListEntry( |
351 url, title, state, creation_time_us, first_read_time_us, update_time_us, | 374 url, title, state, creation_time_us, first_read_time_us, update_time_us, |
352 WAITING, base::FilePath(), 0, nullptr)); | 375 update_title_time_us, WAITING, base::FilePath(), 0, nullptr)); |
353 } | 376 } |
354 | 377 |
355 void ReadingListEntry::MergeWithEntry(const ReadingListEntry& other) { | 378 void ReadingListEntry::MergeWithEntry(const ReadingListEntry& other) { |
356 #if !defined(NDEBUG) | 379 #if !defined(NDEBUG) |
357 // Checks that the result entry respects the sync order. | 380 // Checks that the result entry respects the sync order. |
358 std::unique_ptr<sync_pb::ReadingListSpecifics> old_this_pb( | 381 std::unique_ptr<sync_pb::ReadingListSpecifics> old_this_pb( |
359 AsReadingListSpecifics()); | 382 AsReadingListSpecifics()); |
360 std::unique_ptr<sync_pb::ReadingListSpecifics> other_pb( | 383 std::unique_ptr<sync_pb::ReadingListSpecifics> other_pb( |
361 other.AsReadingListSpecifics()); | 384 other.AsReadingListSpecifics()); |
362 #endif | 385 #endif |
363 DCHECK(url_ == other.url_); | 386 DCHECK(url_ == other.url_); |
364 if (title_.compare(other.title_) < 0) { | 387 if (update_title_time_us_ < other.update_title_time_us_) { |
365 // Take the last in alphabetical order or the longer one. | 388 // Take the most recent title updated. |
366 // This ensure empty string is replaced. | |
367 title_ = std::move(other.title_); | 389 title_ = std::move(other.title_); |
Olivier
2016/12/21 15:14:01
what if there is a tie?
gambard
2016/12/21 16:38:00
Done.
| |
390 update_title_time_us_ = std::move(other.update_title_time_us_); | |
368 } | 391 } |
369 if (creation_time_us_ < other.creation_time_us_) { | 392 if (creation_time_us_ < other.creation_time_us_) { |
370 creation_time_us_ = std::move(other.creation_time_us_); | 393 creation_time_us_ = std::move(other.creation_time_us_); |
371 first_read_time_us_ = std::move(other.first_read_time_us_); | 394 first_read_time_us_ = std::move(other.first_read_time_us_); |
372 } else if (creation_time_us_ == other.creation_time_us_) { | 395 } else if (creation_time_us_ == other.creation_time_us_) { |
373 // The first_time_read_us from |other| is used if | 396 // The first_time_read_us from |other| is used if |
374 // - this.first_time_read_us == 0: the entry was never read in this device. | 397 // - this.first_time_read_us == 0: the entry was never read in this device. |
375 // - this.first_time_read_us > other.first_time_read_us: the entry was | 398 // - this.first_time_read_us > other.first_time_read_us: the entry was |
376 // first read on another device. | 399 // first read on another device. |
377 if (first_read_time_us_ == 0 || | 400 if (first_read_time_us_ == 0 || |
(...skipping 26 matching lines...) Expand all Loading... | |
404 base::MakeUnique<reading_list::ReadingListLocal>(); | 427 base::MakeUnique<reading_list::ReadingListLocal>(); |
405 | 428 |
406 // URL is used as the key for the database and sync as there is only one entry | 429 // URL is used as the key for the database and sync as there is only one entry |
407 // per URL. | 430 // per URL. |
408 pb_entry->set_entry_id(URL().spec()); | 431 pb_entry->set_entry_id(URL().spec()); |
409 pb_entry->set_title(Title()); | 432 pb_entry->set_title(Title()); |
410 pb_entry->set_url(URL().spec()); | 433 pb_entry->set_url(URL().spec()); |
411 pb_entry->set_creation_time_us(CreationTime()); | 434 pb_entry->set_creation_time_us(CreationTime()); |
412 pb_entry->set_first_read_time_us(FirstReadTime()); | 435 pb_entry->set_first_read_time_us(FirstReadTime()); |
413 pb_entry->set_update_time_us(UpdateTime()); | 436 pb_entry->set_update_time_us(UpdateTime()); |
437 pb_entry->set_update_title_time_us(UpdateTitleTime()); | |
414 | 438 |
415 switch (state_) { | 439 switch (state_) { |
416 case READ: | 440 case READ: |
417 pb_entry->set_status(reading_list::ReadingListLocal::READ); | 441 pb_entry->set_status(reading_list::ReadingListLocal::READ); |
418 break; | 442 break; |
419 case UNREAD: | 443 case UNREAD: |
420 pb_entry->set_status(reading_list::ReadingListLocal::UNREAD); | 444 pb_entry->set_status(reading_list::ReadingListLocal::UNREAD); |
421 break; | 445 break; |
422 case UNSEEN: | 446 case UNSEEN: |
423 pb_entry->set_status(reading_list::ReadingListLocal::UNSEEN); | 447 pb_entry->set_status(reading_list::ReadingListLocal::UNSEEN); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 base::MakeUnique<sync_pb::ReadingListSpecifics>(); | 491 base::MakeUnique<sync_pb::ReadingListSpecifics>(); |
468 | 492 |
469 // URL is used as the key for the database and sync as there is only one entry | 493 // URL is used as the key for the database and sync as there is only one entry |
470 // per URL. | 494 // per URL. |
471 pb_entry->set_entry_id(URL().spec()); | 495 pb_entry->set_entry_id(URL().spec()); |
472 pb_entry->set_title(Title()); | 496 pb_entry->set_title(Title()); |
473 pb_entry->set_url(URL().spec()); | 497 pb_entry->set_url(URL().spec()); |
474 pb_entry->set_creation_time_us(CreationTime()); | 498 pb_entry->set_creation_time_us(CreationTime()); |
475 pb_entry->set_first_read_time_us(FirstReadTime()); | 499 pb_entry->set_first_read_time_us(FirstReadTime()); |
476 pb_entry->set_update_time_us(UpdateTime()); | 500 pb_entry->set_update_time_us(UpdateTime()); |
501 pb_entry->set_update_title_time_us(UpdateTitleTime()); | |
477 | 502 |
478 switch (state_) { | 503 switch (state_) { |
479 case READ: | 504 case READ: |
480 pb_entry->set_status(sync_pb::ReadingListSpecifics::READ); | 505 pb_entry->set_status(sync_pb::ReadingListSpecifics::READ); |
481 break; | 506 break; |
482 case UNREAD: | 507 case UNREAD: |
483 pb_entry->set_status(sync_pb::ReadingListSpecifics::UNREAD); | 508 pb_entry->set_status(sync_pb::ReadingListSpecifics::UNREAD); |
484 break; | 509 break; |
485 case UNSEEN: | 510 case UNSEEN: |
486 pb_entry->set_status(sync_pb::ReadingListSpecifics::UNSEEN); | 511 pb_entry->set_status(sync_pb::ReadingListSpecifics::UNSEEN); |
487 break; | 512 break; |
488 } | 513 } |
489 | 514 |
490 return pb_entry; | 515 return pb_entry; |
491 } | 516 } |
OLD | NEW |