| OLD | NEW |
| (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 "components/reading_list/ios/reading_list_entry.h" | |
| 6 | |
| 7 #include "base/json/json_string_value_serializer.h" | |
| 8 #include "base/memory/ptr_util.h" | |
| 9 #include "components/reading_list/ios/offline_url_utils.h" | |
| 10 #include "components/reading_list/ios/proto/reading_list.pb.h" | |
| 11 #include "components/reading_list/ios/reading_list_store.h" | |
| 12 #include "components/sync/protocol/reading_list_specifics.pb.h" | |
| 13 #include "net/base/backoff_entry_serializer.h" | |
| 14 | |
| 15 namespace { | |
| 16 // Converts |time| to the number of microseconds since Jan 1st 1970. | |
| 17 int64_t TimeToUS(const base::Time& time) { | |
| 18 return (time - base::Time::UnixEpoch()).InMicroseconds(); | |
| 19 } | |
| 20 } | |
| 21 | |
| 22 // The backoff time is the following: 10min, 10min, 1h, 2h, 2h..., starting | |
| 23 // after the first failure. | |
| 24 const net::BackoffEntry::Policy ReadingListEntry::kBackoffPolicy = { | |
| 25 // Number of initial errors (in sequence) to ignore before applying | |
| 26 // exponential back-off rules. | |
| 27 2, | |
| 28 | |
| 29 // Initial delay for exponential back-off in ms. | |
| 30 10 * 60 * 1000, // 10 minutes. | |
| 31 | |
| 32 // Factor by which the waiting time will be multiplied. | |
| 33 6, | |
| 34 | |
| 35 // Fuzzing percentage. ex: 10% will spread requests randomly | |
| 36 // between 90%-100% of the calculated time. | |
| 37 0.1, // 10%. | |
| 38 | |
| 39 // Maximum amount of time we are willing to delay our request in ms. | |
| 40 2 * 3600 * 1000, // 2 hours. | |
| 41 | |
| 42 // Time to keep an entry from being discarded even when it | |
| 43 // has no significant state, -1 to never discard. | |
| 44 -1, | |
| 45 | |
| 46 true, // Don't use initial delay unless the last request was an error. | |
| 47 }; | |
| 48 | |
| 49 ReadingListEntry::ReadingListEntry(const GURL& url, | |
| 50 const std::string& title, | |
| 51 const base::Time& now) | |
| 52 : ReadingListEntry(url, title, now, nullptr){}; | |
| 53 | |
| 54 ReadingListEntry::ReadingListEntry(const GURL& url, | |
| 55 const std::string& title, | |
| 56 const base::Time& now, | |
| 57 std::unique_ptr<net::BackoffEntry> backoff) | |
| 58 : ReadingListEntry(url, | |
| 59 title, | |
| 60 UNSEEN, | |
| 61 TimeToUS(now), | |
| 62 0, | |
| 63 TimeToUS(now), | |
| 64 TimeToUS(now), | |
| 65 WAITING, | |
| 66 base::FilePath(), | |
| 67 GURL(), | |
| 68 0, | |
| 69 0, | |
| 70 0, | |
| 71 std::move(backoff)) {} | |
| 72 | |
| 73 ReadingListEntry::ReadingListEntry( | |
| 74 const GURL& url, | |
| 75 const std::string& title, | |
| 76 State state, | |
| 77 int64_t creation_time, | |
| 78 int64_t first_read_time, | |
| 79 int64_t update_time, | |
| 80 int64_t update_title_time, | |
| 81 ReadingListEntry::DistillationState distilled_state, | |
| 82 const base::FilePath& distilled_path, | |
| 83 const GURL& distilled_url, | |
| 84 int64_t distillation_time, | |
| 85 int64_t distillation_size, | |
| 86 int failed_download_counter, | |
| 87 std::unique_ptr<net::BackoffEntry> backoff) | |
| 88 : url_(url), | |
| 89 title_(title), | |
| 90 state_(state), | |
| 91 distilled_path_(distilled_path), | |
| 92 distilled_url_(distilled_url), | |
| 93 distilled_state_(distilled_state), | |
| 94 failed_download_counter_(failed_download_counter), | |
| 95 creation_time_us_(creation_time), | |
| 96 first_read_time_us_(first_read_time), | |
| 97 update_time_us_(update_time), | |
| 98 update_title_time_us_(update_title_time), | |
| 99 distillation_time_us_(distillation_time), | |
| 100 distillation_size_(distillation_size) { | |
| 101 if (backoff) { | |
| 102 backoff_ = std::move(backoff); | |
| 103 } else { | |
| 104 backoff_ = base::MakeUnique<net::BackoffEntry>(&kBackoffPolicy); | |
| 105 } | |
| 106 DCHECK(creation_time_us_); | |
| 107 DCHECK(update_time_us_); | |
| 108 DCHECK(update_title_time_us_); | |
| 109 DCHECK(!url.is_empty()); | |
| 110 DCHECK(url.is_valid()); | |
| 111 } | |
| 112 | |
| 113 ReadingListEntry::ReadingListEntry(ReadingListEntry&& entry) | |
| 114 : url_(std::move(entry.url_)), | |
| 115 title_(std::move(entry.title_)), | |
| 116 state_(std::move(entry.state_)), | |
| 117 distilled_path_(std::move(entry.distilled_path_)), | |
| 118 distilled_url_(std::move(entry.distilled_url_)), | |
| 119 distilled_state_(std::move(entry.distilled_state_)), | |
| 120 backoff_(std::move(entry.backoff_)), | |
| 121 failed_download_counter_(std::move(entry.failed_download_counter_)), | |
| 122 creation_time_us_(std::move(entry.creation_time_us_)), | |
| 123 first_read_time_us_(std::move(entry.first_read_time_us_)), | |
| 124 update_time_us_(std::move(entry.update_time_us_)), | |
| 125 update_title_time_us_(std::move(entry.update_title_time_us_)), | |
| 126 distillation_time_us_(std::move(entry.distillation_time_us_)), | |
| 127 distillation_size_(std::move(entry.distillation_size_)) {} | |
| 128 | |
| 129 ReadingListEntry::~ReadingListEntry() {} | |
| 130 | |
| 131 const GURL& ReadingListEntry::URL() const { | |
| 132 return url_; | |
| 133 } | |
| 134 | |
| 135 const std::string& ReadingListEntry::Title() const { | |
| 136 return title_; | |
| 137 } | |
| 138 | |
| 139 ReadingListEntry::DistillationState ReadingListEntry::DistilledState() const { | |
| 140 return distilled_state_; | |
| 141 } | |
| 142 | |
| 143 const base::FilePath& ReadingListEntry::DistilledPath() const { | |
| 144 return distilled_path_; | |
| 145 } | |
| 146 | |
| 147 const GURL& ReadingListEntry::DistilledURL() const { | |
| 148 return distilled_url_; | |
| 149 } | |
| 150 | |
| 151 int64_t ReadingListEntry::DistillationTime() const { | |
| 152 return distillation_time_us_; | |
| 153 } | |
| 154 | |
| 155 int64_t ReadingListEntry::DistillationSize() const { | |
| 156 return distillation_size_; | |
| 157 } | |
| 158 | |
| 159 base::TimeDelta ReadingListEntry::TimeUntilNextTry() const { | |
| 160 return backoff_->GetTimeUntilRelease(); | |
| 161 } | |
| 162 | |
| 163 int ReadingListEntry::FailedDownloadCounter() const { | |
| 164 return failed_download_counter_; | |
| 165 } | |
| 166 | |
| 167 ReadingListEntry& ReadingListEntry::operator=(ReadingListEntry&& other) { | |
| 168 url_ = std::move(other.url_); | |
| 169 title_ = std::move(other.title_); | |
| 170 distilled_path_ = std::move(other.distilled_path_); | |
| 171 distilled_url_ = std::move(other.distilled_url_); | |
| 172 distilled_state_ = std::move(other.distilled_state_); | |
| 173 backoff_ = std::move(other.backoff_); | |
| 174 state_ = std::move(other.state_); | |
| 175 failed_download_counter_ = std::move(other.failed_download_counter_); | |
| 176 creation_time_us_ = std::move(other.creation_time_us_); | |
| 177 first_read_time_us_ = std::move(other.first_read_time_us_); | |
| 178 update_time_us_ = std::move(other.update_time_us_); | |
| 179 update_title_time_us_ = std::move(other.update_title_time_us_); | |
| 180 distillation_time_us_ = std::move(other.distillation_time_us_); | |
| 181 distillation_size_ = std::move(other.distillation_size_); | |
| 182 return *this; | |
| 183 } | |
| 184 | |
| 185 bool ReadingListEntry::operator==(const ReadingListEntry& other) const { | |
| 186 return url_ == other.url_; | |
| 187 } | |
| 188 | |
| 189 void ReadingListEntry::SetTitle(const std::string& title, | |
| 190 const base::Time& now) { | |
| 191 title_ = title; | |
| 192 update_title_time_us_ = TimeToUS(now); | |
| 193 } | |
| 194 | |
| 195 void ReadingListEntry::SetRead(bool read, const base::Time& now) { | |
| 196 State previous_state = state_; | |
| 197 state_ = read ? READ : UNREAD; | |
| 198 if (state_ == previous_state) { | |
| 199 return; | |
| 200 } | |
| 201 if (FirstReadTime() == 0 && read) { | |
| 202 first_read_time_us_ = TimeToUS(now); | |
| 203 } | |
| 204 if (!(previous_state == UNSEEN && state_ == UNREAD)) { | |
| 205 // If changing UNSEEN -> UNREAD, entry is not marked updated to preserve | |
| 206 // order in Reading List View. | |
| 207 MarkEntryUpdated(now); | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 bool ReadingListEntry::IsRead() const { | |
| 212 return state_ == READ; | |
| 213 } | |
| 214 | |
| 215 bool ReadingListEntry::HasBeenSeen() const { | |
| 216 return state_ != UNSEEN; | |
| 217 } | |
| 218 | |
| 219 void ReadingListEntry::SetDistilledInfo(const base::FilePath& path, | |
| 220 const GURL& distilled_url, | |
| 221 int64_t distilation_size, | |
| 222 const base::Time& distilation_time) { | |
| 223 DCHECK(!path.empty()); | |
| 224 DCHECK(distilled_url.is_valid()); | |
| 225 distilled_path_ = path; | |
| 226 distilled_state_ = PROCESSED; | |
| 227 distilled_url_ = distilled_url; | |
| 228 distillation_time_us_ = TimeToUS(distilation_time); | |
| 229 distillation_size_ = distilation_size; | |
| 230 backoff_->Reset(); | |
| 231 failed_download_counter_ = 0; | |
| 232 } | |
| 233 | |
| 234 void ReadingListEntry::SetDistilledState(DistillationState distilled_state) { | |
| 235 DCHECK(distilled_state != PROCESSED); // use SetDistilledPath instead. | |
| 236 DCHECK(distilled_state != WAITING); | |
| 237 // Increase time until next retry exponentially if the state change from a | |
| 238 // non-error state to an error state. | |
| 239 if ((distilled_state == WILL_RETRY || distilled_state == ERROR) && | |
| 240 distilled_state_ != WILL_RETRY && distilled_state_ != ERROR) { | |
| 241 backoff_->InformOfRequest(false); | |
| 242 failed_download_counter_++; | |
| 243 } | |
| 244 | |
| 245 distilled_state_ = distilled_state; | |
| 246 distilled_path_ = base::FilePath(); | |
| 247 distilled_url_ = GURL::EmptyGURL(); | |
| 248 } | |
| 249 | |
| 250 int64_t ReadingListEntry::UpdateTime() const { | |
| 251 return update_time_us_; | |
| 252 } | |
| 253 | |
| 254 int64_t ReadingListEntry::UpdateTitleTime() const { | |
| 255 return update_title_time_us_; | |
| 256 } | |
| 257 | |
| 258 int64_t ReadingListEntry::CreationTime() const { | |
| 259 return creation_time_us_; | |
| 260 } | |
| 261 | |
| 262 int64_t ReadingListEntry::FirstReadTime() const { | |
| 263 return first_read_time_us_; | |
| 264 } | |
| 265 | |
| 266 void ReadingListEntry::MarkEntryUpdated(const base::Time& now) { | |
| 267 update_time_us_ = TimeToUS(now); | |
| 268 } | |
| 269 | |
| 270 // static | |
| 271 std::unique_ptr<ReadingListEntry> ReadingListEntry::FromReadingListLocal( | |
| 272 const reading_list::ReadingListLocal& pb_entry, | |
| 273 const base::Time& now) { | |
| 274 if (!pb_entry.has_url()) { | |
| 275 return nullptr; | |
| 276 } | |
| 277 GURL url(pb_entry.url()); | |
| 278 if (url.is_empty() || !url.is_valid()) { | |
| 279 return nullptr; | |
| 280 } | |
| 281 std::string title; | |
| 282 if (pb_entry.has_title()) { | |
| 283 title = pb_entry.title(); | |
| 284 } | |
| 285 | |
| 286 int64_t creation_time_us = 0; | |
| 287 if (pb_entry.has_creation_time_us()) { | |
| 288 creation_time_us = pb_entry.creation_time_us(); | |
| 289 } else { | |
| 290 creation_time_us = (now - base::Time::UnixEpoch()).InMicroseconds(); | |
| 291 } | |
| 292 | |
| 293 int64_t first_read_time_us = 0; | |
| 294 if (pb_entry.has_first_read_time_us()) { | |
| 295 first_read_time_us = pb_entry.first_read_time_us(); | |
| 296 } | |
| 297 | |
| 298 int64_t update_time_us = creation_time_us; | |
| 299 if (pb_entry.has_update_time_us()) { | |
| 300 update_time_us = pb_entry.update_time_us(); | |
| 301 } | |
| 302 | |
| 303 int64_t update_title_time_us = creation_time_us; | |
| 304 if (pb_entry.has_update_title_time_us()) { | |
| 305 update_title_time_us = pb_entry.update_title_time_us(); | |
| 306 } | |
| 307 | |
| 308 State state = UNSEEN; | |
| 309 if (pb_entry.has_status()) { | |
| 310 switch (pb_entry.status()) { | |
| 311 case reading_list::ReadingListLocal::READ: | |
| 312 state = READ; | |
| 313 break; | |
| 314 case reading_list::ReadingListLocal::UNREAD: | |
| 315 state = UNREAD; | |
| 316 break; | |
| 317 case reading_list::ReadingListLocal::UNSEEN: | |
| 318 state = UNSEEN; | |
| 319 break; | |
| 320 } | |
| 321 } | |
| 322 | |
| 323 ReadingListEntry::DistillationState distillation_state = | |
| 324 ReadingListEntry::WAITING; | |
| 325 if (pb_entry.has_distillation_state()) { | |
| 326 switch (pb_entry.distillation_state()) { | |
| 327 case reading_list::ReadingListLocal::WAITING: | |
| 328 distillation_state = ReadingListEntry::WAITING; | |
| 329 break; | |
| 330 case reading_list::ReadingListLocal::PROCESSING: | |
| 331 distillation_state = ReadingListEntry::PROCESSING; | |
| 332 break; | |
| 333 case reading_list::ReadingListLocal::PROCESSED: | |
| 334 distillation_state = ReadingListEntry::PROCESSED; | |
| 335 break; | |
| 336 case reading_list::ReadingListLocal::WILL_RETRY: | |
| 337 distillation_state = ReadingListEntry::WILL_RETRY; | |
| 338 break; | |
| 339 case reading_list::ReadingListLocal::ERROR: | |
| 340 distillation_state = ReadingListEntry::ERROR; | |
| 341 break; | |
| 342 } | |
| 343 } | |
| 344 | |
| 345 base::FilePath distilled_path; | |
| 346 if (pb_entry.has_distilled_path()) { | |
| 347 distilled_path = base::FilePath(pb_entry.distilled_path()); | |
| 348 } | |
| 349 | |
| 350 GURL distilled_url; | |
| 351 if (pb_entry.has_distilled_url()) { | |
| 352 distilled_url = GURL(pb_entry.distilled_url()); | |
| 353 } | |
| 354 | |
| 355 int64_t distillation_time_us = 0; | |
| 356 if (pb_entry.has_distillation_time_us()) { | |
| 357 distillation_time_us = pb_entry.distillation_time_us(); | |
| 358 } | |
| 359 | |
| 360 int64_t distillation_size = 0; | |
| 361 if (pb_entry.has_distillation_size()) { | |
| 362 distillation_size = pb_entry.distillation_size(); | |
| 363 } | |
| 364 | |
| 365 int64_t failed_download_counter = 0; | |
| 366 if (pb_entry.has_failed_download_counter()) { | |
| 367 failed_download_counter = pb_entry.failed_download_counter(); | |
| 368 } | |
| 369 | |
| 370 std::unique_ptr<net::BackoffEntry> backoff; | |
| 371 if (pb_entry.has_backoff()) { | |
| 372 JSONStringValueDeserializer deserializer(pb_entry.backoff()); | |
| 373 std::unique_ptr<base::Value> value( | |
| 374 deserializer.Deserialize(nullptr, nullptr)); | |
| 375 if (value) { | |
| 376 backoff = net::BackoffEntrySerializer::DeserializeFromValue( | |
| 377 *value, &kBackoffPolicy, nullptr, now); | |
| 378 } | |
| 379 } | |
| 380 | |
| 381 return base::WrapUnique<ReadingListEntry>(new ReadingListEntry( | |
| 382 url, title, state, creation_time_us, first_read_time_us, update_time_us, | |
| 383 update_title_time_us, distillation_state, distilled_path, distilled_url, | |
| 384 distillation_time_us, distillation_size, failed_download_counter, | |
| 385 std::move(backoff))); | |
| 386 } | |
| 387 | |
| 388 // static | |
| 389 std::unique_ptr<ReadingListEntry> ReadingListEntry::FromReadingListSpecifics( | |
| 390 const sync_pb::ReadingListSpecifics& pb_entry, | |
| 391 const base::Time& now) { | |
| 392 if (!pb_entry.has_url()) { | |
| 393 return nullptr; | |
| 394 } | |
| 395 GURL url(pb_entry.url()); | |
| 396 if (url.is_empty() || !url.is_valid()) { | |
| 397 return nullptr; | |
| 398 } | |
| 399 std::string title; | |
| 400 if (pb_entry.has_title()) { | |
| 401 title = pb_entry.title(); | |
| 402 } | |
| 403 | |
| 404 int64_t creation_time_us = TimeToUS(now); | |
| 405 if (pb_entry.has_creation_time_us()) { | |
| 406 creation_time_us = pb_entry.creation_time_us(); | |
| 407 } | |
| 408 | |
| 409 int64_t first_read_time_us = 0; | |
| 410 if (pb_entry.has_first_read_time_us()) { | |
| 411 first_read_time_us = pb_entry.first_read_time_us(); | |
| 412 } | |
| 413 | |
| 414 int64_t update_time_us = creation_time_us; | |
| 415 if (pb_entry.has_update_time_us()) { | |
| 416 update_time_us = pb_entry.update_time_us(); | |
| 417 } | |
| 418 | |
| 419 int64_t update_title_time_us = creation_time_us; | |
| 420 if (pb_entry.has_update_title_time_us()) { | |
| 421 update_title_time_us = pb_entry.update_title_time_us(); | |
| 422 } | |
| 423 | |
| 424 State state = UNSEEN; | |
| 425 if (pb_entry.has_status()) { | |
| 426 switch (pb_entry.status()) { | |
| 427 case sync_pb::ReadingListSpecifics::READ: | |
| 428 state = READ; | |
| 429 break; | |
| 430 case sync_pb::ReadingListSpecifics::UNREAD: | |
| 431 state = UNREAD; | |
| 432 break; | |
| 433 case sync_pb::ReadingListSpecifics::UNSEEN: | |
| 434 state = UNSEEN; | |
| 435 break; | |
| 436 } | |
| 437 } | |
| 438 | |
| 439 return base::WrapUnique<ReadingListEntry>(new ReadingListEntry( | |
| 440 url, title, state, creation_time_us, first_read_time_us, update_time_us, | |
| 441 update_title_time_us, WAITING, base::FilePath(), GURL(), 0, 0, 0, | |
| 442 nullptr)); | |
| 443 } | |
| 444 | |
| 445 void ReadingListEntry::MergeWithEntry(const ReadingListEntry& other) { | |
| 446 #if !defined(NDEBUG) | |
| 447 // Checks that the result entry respects the sync order. | |
| 448 std::unique_ptr<sync_pb::ReadingListSpecifics> old_this_pb( | |
| 449 AsReadingListSpecifics()); | |
| 450 std::unique_ptr<sync_pb::ReadingListSpecifics> other_pb( | |
| 451 other.AsReadingListSpecifics()); | |
| 452 #endif | |
| 453 DCHECK(url_ == other.url_); | |
| 454 if (update_title_time_us_ < other.update_title_time_us_) { | |
| 455 // Take the most recent title updated. | |
| 456 title_ = std::move(other.title_); | |
| 457 update_title_time_us_ = std::move(other.update_title_time_us_); | |
| 458 } else if (update_title_time_us_ == other.update_title_time_us_) { | |
| 459 if (title_.compare(other.title_) < 0) { | |
| 460 // Take the last in alphabetical order or the longer one. | |
| 461 // This ensure empty string is replaced. | |
| 462 title_ = std::move(other.title_); | |
| 463 } | |
| 464 } | |
| 465 if (creation_time_us_ < other.creation_time_us_) { | |
| 466 creation_time_us_ = std::move(other.creation_time_us_); | |
| 467 first_read_time_us_ = std::move(other.first_read_time_us_); | |
| 468 } else if (creation_time_us_ == other.creation_time_us_) { | |
| 469 // The first_time_read_us from |other| is used if | |
| 470 // - this.first_time_read_us == 0: the entry was never read in this device. | |
| 471 // - this.first_time_read_us > other.first_time_read_us: the entry was | |
| 472 // first read on another device. | |
| 473 if (first_read_time_us_ == 0 || | |
| 474 (other.first_read_time_us_ != 0 && | |
| 475 other.first_read_time_us_ < first_read_time_us_)) { | |
| 476 first_read_time_us_ = std::move(other.first_read_time_us_); | |
| 477 } | |
| 478 } | |
| 479 if (update_time_us_ < other.update_time_us_) { | |
| 480 update_time_us_ = std::move(other.update_time_us_); | |
| 481 state_ = std::move(other.state_); | |
| 482 } else if (update_time_us_ == other.update_time_us_) { | |
| 483 if (state_ == UNSEEN) { | |
| 484 state_ = std::move(other.state_); | |
| 485 } else if (other.state_ == READ) { | |
| 486 state_ = std::move(other.state_); | |
| 487 } | |
| 488 } | |
| 489 #if !defined(NDEBUG) | |
| 490 std::unique_ptr<sync_pb::ReadingListSpecifics> new_this_pb( | |
| 491 AsReadingListSpecifics()); | |
| 492 DCHECK(ReadingListStore::CompareEntriesForSync(*old_this_pb, *new_this_pb)); | |
| 493 DCHECK(ReadingListStore::CompareEntriesForSync(*other_pb, *new_this_pb)); | |
| 494 #endif | |
| 495 } | |
| 496 | |
| 497 std::unique_ptr<reading_list::ReadingListLocal> | |
| 498 ReadingListEntry::AsReadingListLocal(const base::Time& now) const { | |
| 499 std::unique_ptr<reading_list::ReadingListLocal> pb_entry = | |
| 500 base::MakeUnique<reading_list::ReadingListLocal>(); | |
| 501 | |
| 502 // URL is used as the key for the database and sync as there is only one entry | |
| 503 // per URL. | |
| 504 pb_entry->set_entry_id(URL().spec()); | |
| 505 pb_entry->set_title(Title()); | |
| 506 pb_entry->set_url(URL().spec()); | |
| 507 pb_entry->set_creation_time_us(CreationTime()); | |
| 508 pb_entry->set_first_read_time_us(FirstReadTime()); | |
| 509 pb_entry->set_update_time_us(UpdateTime()); | |
| 510 pb_entry->set_update_title_time_us(UpdateTitleTime()); | |
| 511 | |
| 512 switch (state_) { | |
| 513 case READ: | |
| 514 pb_entry->set_status(reading_list::ReadingListLocal::READ); | |
| 515 break; | |
| 516 case UNREAD: | |
| 517 pb_entry->set_status(reading_list::ReadingListLocal::UNREAD); | |
| 518 break; | |
| 519 case UNSEEN: | |
| 520 pb_entry->set_status(reading_list::ReadingListLocal::UNSEEN); | |
| 521 break; | |
| 522 } | |
| 523 | |
| 524 reading_list::ReadingListLocal::DistillationState distilation_state; | |
| 525 switch (DistilledState()) { | |
| 526 case ReadingListEntry::WAITING: | |
| 527 distilation_state = reading_list::ReadingListLocal::WAITING; | |
| 528 break; | |
| 529 case ReadingListEntry::PROCESSING: | |
| 530 distilation_state = reading_list::ReadingListLocal::PROCESSING; | |
| 531 break; | |
| 532 case ReadingListEntry::PROCESSED: | |
| 533 distilation_state = reading_list::ReadingListLocal::PROCESSED; | |
| 534 break; | |
| 535 case ReadingListEntry::WILL_RETRY: | |
| 536 distilation_state = reading_list::ReadingListLocal::WILL_RETRY; | |
| 537 break; | |
| 538 case ReadingListEntry::ERROR: | |
| 539 distilation_state = reading_list::ReadingListLocal::ERROR; | |
| 540 break; | |
| 541 } | |
| 542 pb_entry->set_distillation_state(distilation_state); | |
| 543 if (!DistilledPath().empty()) { | |
| 544 pb_entry->set_distilled_path(DistilledPath().value()); | |
| 545 } | |
| 546 if (DistilledURL().is_valid()) { | |
| 547 pb_entry->set_distilled_url(DistilledURL().spec()); | |
| 548 } | |
| 549 if (DistillationTime()) { | |
| 550 pb_entry->set_distillation_time_us(DistillationTime()); | |
| 551 } | |
| 552 if (DistillationSize()) { | |
| 553 pb_entry->set_distillation_size(DistillationSize()); | |
| 554 } | |
| 555 | |
| 556 pb_entry->set_failed_download_counter(failed_download_counter_); | |
| 557 | |
| 558 if (backoff_) { | |
| 559 std::unique_ptr<base::Value> backoff = | |
| 560 net::BackoffEntrySerializer::SerializeToValue(*backoff_, now); | |
| 561 | |
| 562 std::string output; | |
| 563 JSONStringValueSerializer serializer(&output); | |
| 564 serializer.Serialize(*backoff); | |
| 565 pb_entry->set_backoff(output); | |
| 566 } | |
| 567 return pb_entry; | |
| 568 } | |
| 569 | |
| 570 std::unique_ptr<sync_pb::ReadingListSpecifics> | |
| 571 ReadingListEntry::AsReadingListSpecifics() const { | |
| 572 std::unique_ptr<sync_pb::ReadingListSpecifics> pb_entry = | |
| 573 base::MakeUnique<sync_pb::ReadingListSpecifics>(); | |
| 574 | |
| 575 // URL is used as the key for the database and sync as there is only one entry | |
| 576 // per URL. | |
| 577 pb_entry->set_entry_id(URL().spec()); | |
| 578 pb_entry->set_title(Title()); | |
| 579 pb_entry->set_url(URL().spec()); | |
| 580 pb_entry->set_creation_time_us(CreationTime()); | |
| 581 pb_entry->set_first_read_time_us(FirstReadTime()); | |
| 582 pb_entry->set_update_time_us(UpdateTime()); | |
| 583 pb_entry->set_update_title_time_us(UpdateTitleTime()); | |
| 584 | |
| 585 switch (state_) { | |
| 586 case READ: | |
| 587 pb_entry->set_status(sync_pb::ReadingListSpecifics::READ); | |
| 588 break; | |
| 589 case UNREAD: | |
| 590 pb_entry->set_status(sync_pb::ReadingListSpecifics::UNREAD); | |
| 591 break; | |
| 592 case UNSEEN: | |
| 593 pb_entry->set_status(sync_pb::ReadingListSpecifics::UNSEEN); | |
| 594 break; | |
| 595 } | |
| 596 | |
| 597 return pb_entry; | |
| 598 } | |
| OLD | NEW |