| 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 "ios/chrome/browser/reading_list/reading_list_entry.h" | 5 #include "ios/chrome/browser/reading_list/reading_list_entry.h" | 
| 6 | 6 | 
|  | 7 #include "base/json/json_string_value_serializer.h" | 
| 7 #include "base/memory/ptr_util.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/proto/reading_list.pb.h" | 
|  | 11 #include "net/base/backoff_entry_serializer.h" | 
| 8 | 12 | 
| 9 // The backoff time is the following: 10min, 10min, 1h, 2h, 2h..., starting | 13 // The backoff time is the following: 10min, 10min, 1h, 2h, 2h..., starting | 
| 10 // after the first failure. | 14 // after the first failure. | 
| 11 const net::BackoffEntry::Policy ReadingListEntry::kBackoffPolicy = { | 15 const net::BackoffEntry::Policy ReadingListEntry::kBackoffPolicy = { | 
| 12     // Number of initial errors (in sequence) to ignore before applying | 16     // Number of initial errors (in sequence) to ignore before applying | 
| 13     // exponential back-off rules. | 17     // exponential back-off rules. | 
| 14     2, | 18     2, | 
| 15 | 19 | 
| 16     // Initial delay for exponential back-off in ms. | 20     // Initial delay for exponential back-off in ms. | 
| 17     10 * 60 * 1000,  // 10 minutes. | 21     10 * 60 * 1000,  // 10 minutes. | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 32 | 36 | 
| 33     true,  // Don't use initial delay unless the last request was an error. | 37     true,  // Don't use initial delay unless the last request was an error. | 
| 34 }; | 38 }; | 
| 35 | 39 | 
| 36 ReadingListEntry::ReadingListEntry(const GURL& url, const std::string& title) | 40 ReadingListEntry::ReadingListEntry(const GURL& url, const std::string& title) | 
| 37     : ReadingListEntry(url, title, nullptr){}; | 41     : ReadingListEntry(url, title, nullptr){}; | 
| 38 | 42 | 
| 39 ReadingListEntry::ReadingListEntry(const GURL& url, | 43 ReadingListEntry::ReadingListEntry(const GURL& url, | 
| 40                                    const std::string& title, | 44                                    const std::string& title, | 
| 41                                    std::unique_ptr<net::BackoffEntry> backoff) | 45                                    std::unique_ptr<net::BackoffEntry> backoff) | 
|  | 46     : ReadingListEntry(url, | 
|  | 47                        title, | 
|  | 48                        0, | 
|  | 49                        0, | 
|  | 50                        WAITING, | 
|  | 51                        GURL(), | 
|  | 52                        0, | 
|  | 53                        std::move(backoff)) {} | 
|  | 54 | 
|  | 55 ReadingListEntry::ReadingListEntry( | 
|  | 56     const GURL& url, | 
|  | 57     const std::string& title, | 
|  | 58     int64_t creation_time, | 
|  | 59     int64_t update_time, | 
|  | 60     ReadingListEntry::DistillationState distilled_state, | 
|  | 61     const GURL& distilled_url, | 
|  | 62     int failed_download_counter, | 
|  | 63     std::unique_ptr<net::BackoffEntry> backoff) | 
| 42     : url_(url), | 64     : url_(url), | 
| 43       title_(title), | 65       title_(title), | 
| 44       distilled_state_(WAITING), | 66       distilled_url_(distilled_url), | 
| 45       failed_download_counter_(0) { | 67       distilled_state_(distilled_state), | 
|  | 68       failed_download_counter_(failed_download_counter), | 
|  | 69       creation_time_us_(creation_time), | 
|  | 70       update_time_us_(update_time) { | 
| 46   if (backoff) { | 71   if (backoff) { | 
| 47     backoff_ = std::move(backoff); | 72     backoff_ = std::move(backoff); | 
| 48   } else { | 73   } else { | 
| 49     backoff_ = base::MakeUnique<net::BackoffEntry>(&kBackoffPolicy); | 74     backoff_ = base::MakeUnique<net::BackoffEntry>(&kBackoffPolicy); | 
| 50   } | 75   } | 
|  | 76   if (creation_time_us_ == 0) { | 
|  | 77     DCHECK(update_time_us_ == 0); | 
|  | 78     creation_time_us_ = | 
|  | 79         (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds(); | 
|  | 80     update_time_us_ = creation_time_us_; | 
|  | 81   } | 
| 51   DCHECK(!url.is_empty()); | 82   DCHECK(!url.is_empty()); | 
| 52   DCHECK(url.is_valid()); | 83   DCHECK(url.is_valid()); | 
| 53 } | 84 } | 
| 54 | 85 | 
| 55 ReadingListEntry::ReadingListEntry(ReadingListEntry&& entry) | 86 ReadingListEntry::ReadingListEntry(ReadingListEntry&& entry) | 
| 56     : url_(std::move(entry.url_)), | 87     : url_(std::move(entry.url_)), | 
| 57       title_(std::move(entry.title_)), | 88       title_(std::move(entry.title_)), | 
| 58       distilled_url_(std::move(entry.distilled_url_)), | 89       distilled_url_(std::move(entry.distilled_url_)), | 
| 59       distilled_state_(std::move(entry.distilled_state_)), | 90       distilled_state_(std::move(entry.distilled_state_)), | 
| 60       backoff_(std::move(entry.backoff_)), | 91       backoff_(std::move(entry.backoff_)), | 
| 61       failed_download_counter_(std::move(entry.failed_download_counter_)) {} | 92       failed_download_counter_(std::move(entry.failed_download_counter_)), | 
|  | 93       creation_time_us_(std::move(entry.creation_time_us_)), | 
|  | 94       update_time_us_(std::move(entry.update_time_us_)) {} | 
| 62 | 95 | 
| 63 ReadingListEntry::~ReadingListEntry() {} | 96 ReadingListEntry::~ReadingListEntry() {} | 
| 64 | 97 | 
| 65 const GURL& ReadingListEntry::URL() const { | 98 const GURL& ReadingListEntry::URL() const { | 
| 66   return url_; | 99   return url_; | 
| 67 } | 100 } | 
| 68 | 101 | 
| 69 const std::string& ReadingListEntry::Title() const { | 102 const std::string& ReadingListEntry::Title() const { | 
| 70   return title_; | 103   return title_; | 
| 71 } | 104 } | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 86   return failed_download_counter_; | 119   return failed_download_counter_; | 
| 87 } | 120 } | 
| 88 | 121 | 
| 89 ReadingListEntry& ReadingListEntry::operator=(ReadingListEntry&& other) { | 122 ReadingListEntry& ReadingListEntry::operator=(ReadingListEntry&& other) { | 
| 90   url_ = std::move(other.url_); | 123   url_ = std::move(other.url_); | 
| 91   title_ = std::move(other.title_); | 124   title_ = std::move(other.title_); | 
| 92   distilled_url_ = std::move(other.distilled_url_); | 125   distilled_url_ = std::move(other.distilled_url_); | 
| 93   distilled_state_ = std::move(other.distilled_state_); | 126   distilled_state_ = std::move(other.distilled_state_); | 
| 94   backoff_ = std::move(other.backoff_); | 127   backoff_ = std::move(other.backoff_); | 
| 95   failed_download_counter_ = std::move(other.failed_download_counter_); | 128   failed_download_counter_ = std::move(other.failed_download_counter_); | 
|  | 129   creation_time_us_ = std::move(other.creation_time_us_); | 
|  | 130   update_time_us_ = std::move(other.update_time_us_); | 
| 96   return *this; | 131   return *this; | 
| 97 } | 132 } | 
| 98 | 133 | 
| 99 bool ReadingListEntry::operator==(const ReadingListEntry& other) const { | 134 bool ReadingListEntry::operator==(const ReadingListEntry& other) const { | 
| 100   return url_ == other.url_; | 135   return url_ == other.url_; | 
| 101 } | 136 } | 
| 102 | 137 | 
| 103 void ReadingListEntry::SetTitle(const std::string& title) { | 138 void ReadingListEntry::SetTitle(const std::string& title) { | 
| 104   title_ = title; | 139   title_ = title; | 
| 105 } | 140 } | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 119   // non-error state to an error state. | 154   // non-error state to an error state. | 
| 120   if ((distilled_state == WILL_RETRY || distilled_state == ERROR) && | 155   if ((distilled_state == WILL_RETRY || distilled_state == ERROR) && | 
| 121       distilled_state_ != WILL_RETRY && distilled_state_ != ERROR) { | 156       distilled_state_ != WILL_RETRY && distilled_state_ != ERROR) { | 
| 122     backoff_->InformOfRequest(false); | 157     backoff_->InformOfRequest(false); | 
| 123     failed_download_counter_++; | 158     failed_download_counter_++; | 
| 124   } | 159   } | 
| 125 | 160 | 
| 126   distilled_state_ = distilled_state; | 161   distilled_state_ = distilled_state; | 
| 127   distilled_url_ = GURL(); | 162   distilled_url_ = GURL(); | 
| 128 } | 163 } | 
|  | 164 | 
|  | 165 int64_t ReadingListEntry::UpdateTime() const { | 
|  | 166   return update_time_us_; | 
|  | 167 } | 
|  | 168 | 
|  | 169 int64_t ReadingListEntry::CreationTime() const { | 
|  | 170   return creation_time_us_; | 
|  | 171 } | 
|  | 172 | 
|  | 173 void ReadingListEntry::MarkEntryUpdated() { | 
|  | 174   update_time_us_ = | 
|  | 175       (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds(); | 
|  | 176 } | 
|  | 177 | 
|  | 178 // static | 
|  | 179 std::unique_ptr<ReadingListEntry> ReadingListEntry::FromReadingListLocal( | 
|  | 180     const reading_list::ReadingListLocal& pb_entry) { | 
|  | 181   if (!pb_entry.has_url()) { | 
|  | 182     return nullptr; | 
|  | 183   } | 
|  | 184   GURL url(pb_entry.url()); | 
|  | 185   if (url.is_empty() || !url.is_valid()) { | 
|  | 186     return nullptr; | 
|  | 187   } | 
|  | 188   std::string title; | 
|  | 189   if (pb_entry.has_title()) { | 
|  | 190     title = pb_entry.title(); | 
|  | 191   } | 
|  | 192 | 
|  | 193   int64_t creation_time_us = 0; | 
|  | 194   if (pb_entry.has_creation_time_us()) { | 
|  | 195     creation_time_us = pb_entry.creation_time_us(); | 
|  | 196   } | 
|  | 197 | 
|  | 198   int64_t update_time_us = 0; | 
|  | 199   if (pb_entry.has_update_time_us()) { | 
|  | 200     update_time_us = pb_entry.update_time_us(); | 
|  | 201   } | 
|  | 202 | 
|  | 203   ReadingListEntry::DistillationState distillation_state = | 
|  | 204       ReadingListEntry::WAITING; | 
|  | 205   if (pb_entry.has_distillation_state()) { | 
|  | 206     switch (pb_entry.distillation_state()) { | 
|  | 207       case reading_list::ReadingListLocal::WAITING: | 
|  | 208         distillation_state = ReadingListEntry::WAITING; | 
|  | 209         break; | 
|  | 210       case reading_list::ReadingListLocal::PROCESSING: | 
|  | 211         distillation_state = ReadingListEntry::PROCESSING; | 
|  | 212         break; | 
|  | 213       case reading_list::ReadingListLocal::PROCESSED: | 
|  | 214         distillation_state = ReadingListEntry::PROCESSED; | 
|  | 215         break; | 
|  | 216       case reading_list::ReadingListLocal::WILL_RETRY: | 
|  | 217         distillation_state = ReadingListEntry::WILL_RETRY; | 
|  | 218         break; | 
|  | 219       case reading_list::ReadingListLocal::ERROR: | 
|  | 220         distillation_state = ReadingListEntry::ERROR; | 
|  | 221         break; | 
|  | 222     } | 
|  | 223   } | 
|  | 224 | 
|  | 225   GURL distilled_url; | 
|  | 226   if (pb_entry.has_distilled_url()) { | 
|  | 227     distilled_url = GURL(pb_entry.distilled_url()); | 
|  | 228   } | 
|  | 229 | 
|  | 230   int64_t failed_download_counter = 0; | 
|  | 231   if (pb_entry.has_failed_download_counter()) { | 
|  | 232     failed_download_counter = pb_entry.failed_download_counter(); | 
|  | 233   } | 
|  | 234 | 
|  | 235   std::unique_ptr<net::BackoffEntry> backoff; | 
|  | 236   if (pb_entry.has_backoff()) { | 
|  | 237     JSONStringValueDeserializer deserializer(pb_entry.backoff()); | 
|  | 238     std::unique_ptr<base::Value> value( | 
|  | 239         deserializer.Deserialize(nullptr, nullptr)); | 
|  | 240     if (value) { | 
|  | 241       backoff = net::BackoffEntrySerializer::DeserializeFromValue( | 
|  | 242           *value, &kBackoffPolicy, nullptr, base::Time::Now()); | 
|  | 243     } | 
|  | 244   } | 
|  | 245 | 
|  | 246   return base::WrapUnique<ReadingListEntry>(new ReadingListEntry( | 
|  | 247       url, title, creation_time_us, update_time_us, distillation_state, | 
|  | 248       distilled_url, failed_download_counter, std::move(backoff))); | 
|  | 249 } | 
|  | 250 | 
|  | 251 // static | 
|  | 252 std::unique_ptr<ReadingListEntry> ReadingListEntry::FromReadingListSpecifics( | 
|  | 253     const sync_pb::ReadingListSpecifics& pb_entry) { | 
|  | 254   if (!pb_entry.has_url()) { | 
|  | 255     return nullptr; | 
|  | 256   } | 
|  | 257   GURL url(pb_entry.url()); | 
|  | 258   if (url.is_empty() || !url.is_valid()) { | 
|  | 259     return nullptr; | 
|  | 260   } | 
|  | 261   std::string title; | 
|  | 262   if (pb_entry.has_title()) { | 
|  | 263     title = pb_entry.title(); | 
|  | 264   } | 
|  | 265 | 
|  | 266   int64_t creation_time_us = 0; | 
|  | 267   if (pb_entry.has_creation_time_us()) { | 
|  | 268     creation_time_us = pb_entry.creation_time_us(); | 
|  | 269   } | 
|  | 270 | 
|  | 271   int64_t update_time_us = 0; | 
|  | 272   if (pb_entry.has_update_time_us()) { | 
|  | 273     update_time_us = pb_entry.update_time_us(); | 
|  | 274   } | 
|  | 275 | 
|  | 276   return base::WrapUnique<ReadingListEntry>( | 
|  | 277       new ReadingListEntry(url, title, creation_time_us, update_time_us, | 
|  | 278                            WAITING, GURL(), 0, nullptr)); | 
|  | 279 } | 
|  | 280 | 
|  | 281 void ReadingListEntry::MergeLocalStateFrom(ReadingListEntry& other) { | 
|  | 282   distilled_url_ = std::move(other.distilled_url_); | 
|  | 283   distilled_state_ = std::move(other.distilled_state_); | 
|  | 284   backoff_ = std::move(other.backoff_); | 
|  | 285   failed_download_counter_ = std::move(other.failed_download_counter_); | 
|  | 286 } | 
|  | 287 | 
|  | 288 std::unique_ptr<reading_list::ReadingListLocal> | 
|  | 289 ReadingListEntry::AsReadingListLocal(bool read) const { | 
|  | 290   std::unique_ptr<reading_list::ReadingListLocal> pb_entry = | 
|  | 291       base::MakeUnique<reading_list::ReadingListLocal>(); | 
|  | 292 | 
|  | 293   // URL is used as the key for the database and sync as there is only one entry | 
|  | 294   // per URL. | 
|  | 295   pb_entry->set_entry_id(URL().spec()); | 
|  | 296   pb_entry->set_title(Title()); | 
|  | 297   pb_entry->set_url(URL().spec()); | 
|  | 298   pb_entry->set_creation_time_us(CreationTime()); | 
|  | 299   pb_entry->set_update_time_us(UpdateTime()); | 
|  | 300 | 
|  | 301   if (read) { | 
|  | 302     pb_entry->set_status(reading_list::ReadingListLocal::READ); | 
|  | 303   } else { | 
|  | 304     pb_entry->set_status(reading_list::ReadingListLocal::UNREAD); | 
|  | 305   } | 
|  | 306 | 
|  | 307   reading_list::ReadingListLocal::DistillationState distilation_state; | 
|  | 308   switch (DistilledState()) { | 
|  | 309     case ReadingListEntry::WAITING: | 
|  | 310       distilation_state = reading_list::ReadingListLocal::WAITING; | 
|  | 311       break; | 
|  | 312     case ReadingListEntry::PROCESSING: | 
|  | 313       distilation_state = reading_list::ReadingListLocal::PROCESSING; | 
|  | 314       break; | 
|  | 315     case ReadingListEntry::PROCESSED: | 
|  | 316       distilation_state = reading_list::ReadingListLocal::PROCESSED; | 
|  | 317       break; | 
|  | 318     case ReadingListEntry::WILL_RETRY: | 
|  | 319       distilation_state = reading_list::ReadingListLocal::WILL_RETRY; | 
|  | 320       break; | 
|  | 321     case ReadingListEntry::ERROR: | 
|  | 322       distilation_state = reading_list::ReadingListLocal::ERROR; | 
|  | 323       break; | 
|  | 324   } | 
|  | 325   pb_entry->set_distillation_state(distilation_state); | 
|  | 326   if (DistilledURL().is_valid()) { | 
|  | 327     pb_entry->set_distilled_url(DistilledURL().spec()); | 
|  | 328   } | 
|  | 329   pb_entry->set_failed_download_counter(failed_download_counter_); | 
|  | 330 | 
|  | 331   if (backoff_) { | 
|  | 332     std::unique_ptr<base::Value> backoff = | 
|  | 333         net::BackoffEntrySerializer::SerializeToValue(*backoff_, | 
|  | 334                                                       base::Time::Now()); | 
|  | 335 | 
|  | 336     std::string output; | 
|  | 337     JSONStringValueSerializer serializer(&output); | 
|  | 338     serializer.Serialize(*backoff); | 
|  | 339     pb_entry->set_backoff(output); | 
|  | 340   } | 
|  | 341   return pb_entry; | 
|  | 342 } | 
|  | 343 | 
|  | 344 std::unique_ptr<sync_pb::ReadingListSpecifics> | 
|  | 345 ReadingListEntry::AsReadingListSpecifics(bool read) const { | 
|  | 346   std::unique_ptr<sync_pb::ReadingListSpecifics> pb_entry = | 
|  | 347       base::MakeUnique<sync_pb::ReadingListSpecifics>(); | 
|  | 348 | 
|  | 349   // URL is used as the key for the database and sync as there is only one entry | 
|  | 350   // per URL. | 
|  | 351   pb_entry->set_entry_id(URL().spec()); | 
|  | 352   pb_entry->set_title(Title()); | 
|  | 353   pb_entry->set_url(URL().spec()); | 
|  | 354   pb_entry->set_creation_time_us(CreationTime()); | 
|  | 355   pb_entry->set_update_time_us(UpdateTime()); | 
|  | 356 | 
|  | 357   if (read) { | 
|  | 358     pb_entry->set_status(sync_pb::ReadingListSpecifics::READ); | 
|  | 359   } else { | 
|  | 360     pb_entry->set_status(sync_pb::ReadingListSpecifics::UNREAD); | 
|  | 361   } | 
|  | 362 | 
|  | 363   return pb_entry; | 
|  | 364 } | 
|  | 365 | 
|  | 366 bool ReadingListEntry::CompareEntryUpdateTime(const ReadingListEntry& lhs, | 
|  | 367                                               const ReadingListEntry& rhs) { | 
|  | 368   return lhs.UpdateTime() > rhs.UpdateTime(); | 
|  | 369 } | 
| OLD | NEW | 
|---|