| 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 namespace { | 13 namespace { |
| 10 // URL used to open offline pages. | 14 // URL used to open offline pages. |
| 11 // This variable will be moved to chrome_url_constants. | 15 // This variable will be moved to chrome_url_constants. |
| 12 const char kChromeUIOfflineURL[] = "chrome://offline/"; | 16 const char kChromeUIOfflineURL[] = "chrome://offline/"; |
| 13 } | 17 } |
| 14 | 18 |
| 15 // The backoff time is the following: 10min, 10min, 1h, 2h, 2h..., starting | 19 // The backoff time is the following: 10min, 10min, 1h, 2h, 2h..., starting |
| 16 // after the first failure. | 20 // after the first failure. |
| 17 const net::BackoffEntry::Policy ReadingListEntry::kBackoffPolicy = { | 21 const net::BackoffEntry::Policy ReadingListEntry::kBackoffPolicy = { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 38 | 42 |
| 39 true, // Don't use initial delay unless the last request was an error. | 43 true, // Don't use initial delay unless the last request was an error. |
| 40 }; | 44 }; |
| 41 | 45 |
| 42 ReadingListEntry::ReadingListEntry(const GURL& url, const std::string& title) | 46 ReadingListEntry::ReadingListEntry(const GURL& url, const std::string& title) |
| 43 : ReadingListEntry(url, title, nullptr){}; | 47 : ReadingListEntry(url, title, nullptr){}; |
| 44 | 48 |
| 45 ReadingListEntry::ReadingListEntry(const GURL& url, | 49 ReadingListEntry::ReadingListEntry(const GURL& url, |
| 46 const std::string& title, | 50 const std::string& title, |
| 47 std::unique_ptr<net::BackoffEntry> backoff) | 51 std::unique_ptr<net::BackoffEntry> backoff) |
| 52 : ReadingListEntry(url, |
| 53 title, |
| 54 0, |
| 55 0, |
| 56 WAITING, |
| 57 base::FilePath(), |
| 58 0, |
| 59 std::move(backoff)) {} |
| 60 |
| 61 ReadingListEntry::ReadingListEntry( |
| 62 const GURL& url, |
| 63 const std::string& title, |
| 64 int64_t creation_time, |
| 65 int64_t update_time, |
| 66 ReadingListEntry::DistillationState distilled_state, |
| 67 const base::FilePath& distilled_path, |
| 68 int failed_download_counter, |
| 69 std::unique_ptr<net::BackoffEntry> backoff) |
| 48 : url_(url), | 70 : url_(url), |
| 49 title_(title), | 71 title_(title), |
| 50 distilled_state_(WAITING), | 72 distilled_path_(distilled_path), |
| 51 failed_download_counter_(0) { | 73 distilled_state_(distilled_state), |
| 74 failed_download_counter_(failed_download_counter), |
| 75 creation_time_us_(creation_time), |
| 76 update_time_us_(update_time) { |
| 52 if (backoff) { | 77 if (backoff) { |
| 53 backoff_ = std::move(backoff); | 78 backoff_ = std::move(backoff); |
| 54 } else { | 79 } else { |
| 55 backoff_ = base::MakeUnique<net::BackoffEntry>(&kBackoffPolicy); | 80 backoff_ = base::MakeUnique<net::BackoffEntry>(&kBackoffPolicy); |
| 56 } | 81 } |
| 82 if (creation_time_us_ == 0) { |
| 83 DCHECK(update_time_us_ == 0); |
| 84 creation_time_us_ = |
| 85 (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds(); |
| 86 update_time_us_ = creation_time_us_; |
| 87 } |
| 57 DCHECK(!url.is_empty()); | 88 DCHECK(!url.is_empty()); |
| 58 DCHECK(url.is_valid()); | 89 DCHECK(url.is_valid()); |
| 59 } | 90 } |
| 60 | 91 |
| 61 ReadingListEntry::ReadingListEntry(ReadingListEntry&& entry) | 92 ReadingListEntry::ReadingListEntry(ReadingListEntry&& entry) |
| 62 : url_(std::move(entry.url_)), | 93 : url_(std::move(entry.url_)), |
| 63 title_(std::move(entry.title_)), | 94 title_(std::move(entry.title_)), |
| 64 distilled_path_(std::move(entry.distilled_path_)), | 95 distilled_path_(std::move(entry.distilled_path_)), |
| 65 distilled_state_(std::move(entry.distilled_state_)), | 96 distilled_state_(std::move(entry.distilled_state_)), |
| 66 backoff_(std::move(entry.backoff_)), | 97 backoff_(std::move(entry.backoff_)), |
| 67 failed_download_counter_(std::move(entry.failed_download_counter_)) {} | 98 failed_download_counter_(std::move(entry.failed_download_counter_)), |
| 99 creation_time_us_(std::move(entry.creation_time_us_)), |
| 100 update_time_us_(std::move(entry.update_time_us_)) {} |
| 68 | 101 |
| 69 ReadingListEntry::~ReadingListEntry() {} | 102 ReadingListEntry::~ReadingListEntry() {} |
| 70 | 103 |
| 71 const GURL& ReadingListEntry::URL() const { | 104 const GURL& ReadingListEntry::URL() const { |
| 72 return url_; | 105 return url_; |
| 73 } | 106 } |
| 74 | 107 |
| 75 const std::string& ReadingListEntry::Title() const { | 108 const std::string& ReadingListEntry::Title() const { |
| 76 return title_; | 109 return title_; |
| 77 } | 110 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 99 return failed_download_counter_; | 132 return failed_download_counter_; |
| 100 } | 133 } |
| 101 | 134 |
| 102 ReadingListEntry& ReadingListEntry::operator=(ReadingListEntry&& other) { | 135 ReadingListEntry& ReadingListEntry::operator=(ReadingListEntry&& other) { |
| 103 url_ = std::move(other.url_); | 136 url_ = std::move(other.url_); |
| 104 title_ = std::move(other.title_); | 137 title_ = std::move(other.title_); |
| 105 distilled_path_ = std::move(other.distilled_path_); | 138 distilled_path_ = std::move(other.distilled_path_); |
| 106 distilled_state_ = std::move(other.distilled_state_); | 139 distilled_state_ = std::move(other.distilled_state_); |
| 107 backoff_ = std::move(other.backoff_); | 140 backoff_ = std::move(other.backoff_); |
| 108 failed_download_counter_ = std::move(other.failed_download_counter_); | 141 failed_download_counter_ = std::move(other.failed_download_counter_); |
| 142 creation_time_us_ = std::move(other.creation_time_us_); |
| 143 update_time_us_ = std::move(other.update_time_us_); |
| 109 return *this; | 144 return *this; |
| 110 } | 145 } |
| 111 | 146 |
| 112 bool ReadingListEntry::operator==(const ReadingListEntry& other) const { | 147 bool ReadingListEntry::operator==(const ReadingListEntry& other) const { |
| 113 return url_ == other.url_; | 148 return url_ == other.url_; |
| 114 } | 149 } |
| 115 | 150 |
| 116 void ReadingListEntry::SetTitle(const std::string& title) { | 151 void ReadingListEntry::SetTitle(const std::string& title) { |
| 117 title_ = title; | 152 title_ = title; |
| 118 } | 153 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 132 // non-error state to an error state. | 167 // non-error state to an error state. |
| 133 if ((distilled_state == WILL_RETRY || distilled_state == ERROR) && | 168 if ((distilled_state == WILL_RETRY || distilled_state == ERROR) && |
| 134 distilled_state_ != WILL_RETRY && distilled_state_ != ERROR) { | 169 distilled_state_ != WILL_RETRY && distilled_state_ != ERROR) { |
| 135 backoff_->InformOfRequest(false); | 170 backoff_->InformOfRequest(false); |
| 136 failed_download_counter_++; | 171 failed_download_counter_++; |
| 137 } | 172 } |
| 138 | 173 |
| 139 distilled_state_ = distilled_state; | 174 distilled_state_ = distilled_state; |
| 140 distilled_path_ = base::FilePath(); | 175 distilled_path_ = base::FilePath(); |
| 141 } | 176 } |
| 177 |
| 178 int64_t ReadingListEntry::UpdateTime() const { |
| 179 return update_time_us_; |
| 180 } |
| 181 |
| 182 int64_t ReadingListEntry::CreationTime() const { |
| 183 return creation_time_us_; |
| 184 } |
| 185 |
| 186 void ReadingListEntry::MarkEntryUpdated() { |
| 187 update_time_us_ = |
| 188 (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds(); |
| 189 } |
| 190 |
| 191 // static |
| 192 std::unique_ptr<ReadingListEntry> ReadingListEntry::FromReadingListLocal( |
| 193 const reading_list::ReadingListLocal& pb_entry) { |
| 194 if (!pb_entry.has_url()) { |
| 195 return nullptr; |
| 196 } |
| 197 GURL url(pb_entry.url()); |
| 198 if (url.is_empty() || !url.is_valid()) { |
| 199 return nullptr; |
| 200 } |
| 201 std::string title; |
| 202 if (pb_entry.has_title()) { |
| 203 title = pb_entry.title(); |
| 204 } |
| 205 |
| 206 int64_t creation_time_us = 0; |
| 207 if (pb_entry.has_creation_time_us()) { |
| 208 creation_time_us = pb_entry.creation_time_us(); |
| 209 } |
| 210 |
| 211 int64_t update_time_us = 0; |
| 212 if (pb_entry.has_update_time_us()) { |
| 213 update_time_us = pb_entry.update_time_us(); |
| 214 } |
| 215 |
| 216 ReadingListEntry::DistillationState distillation_state = |
| 217 ReadingListEntry::WAITING; |
| 218 if (pb_entry.has_distillation_state()) { |
| 219 switch (pb_entry.distillation_state()) { |
| 220 case reading_list::ReadingListLocal::WAITING: |
| 221 distillation_state = ReadingListEntry::WAITING; |
| 222 break; |
| 223 case reading_list::ReadingListLocal::PROCESSING: |
| 224 distillation_state = ReadingListEntry::PROCESSING; |
| 225 break; |
| 226 case reading_list::ReadingListLocal::PROCESSED: |
| 227 distillation_state = ReadingListEntry::PROCESSED; |
| 228 break; |
| 229 case reading_list::ReadingListLocal::WILL_RETRY: |
| 230 distillation_state = ReadingListEntry::WILL_RETRY; |
| 231 break; |
| 232 case reading_list::ReadingListLocal::ERROR: |
| 233 distillation_state = ReadingListEntry::ERROR; |
| 234 break; |
| 235 } |
| 236 } |
| 237 |
| 238 base::FilePath distilled_path; |
| 239 if (pb_entry.has_distilled_path()) { |
| 240 distilled_path = base::FilePath(pb_entry.distilled_path()); |
| 241 } |
| 242 |
| 243 int64_t failed_download_counter = 0; |
| 244 if (pb_entry.has_failed_download_counter()) { |
| 245 failed_download_counter = pb_entry.failed_download_counter(); |
| 246 } |
| 247 |
| 248 std::unique_ptr<net::BackoffEntry> backoff; |
| 249 if (pb_entry.has_backoff()) { |
| 250 JSONStringValueDeserializer deserializer(pb_entry.backoff()); |
| 251 std::unique_ptr<base::Value> value( |
| 252 deserializer.Deserialize(nullptr, nullptr)); |
| 253 if (value) { |
| 254 backoff = net::BackoffEntrySerializer::DeserializeFromValue( |
| 255 *value, &kBackoffPolicy, nullptr, base::Time::Now()); |
| 256 } |
| 257 } |
| 258 |
| 259 return base::WrapUnique<ReadingListEntry>(new ReadingListEntry( |
| 260 url, title, creation_time_us, update_time_us, distillation_state, |
| 261 distilled_path, failed_download_counter, std::move(backoff))); |
| 262 } |
| 263 |
| 264 // static |
| 265 std::unique_ptr<ReadingListEntry> ReadingListEntry::FromReadingListSpecifics( |
| 266 const sync_pb::ReadingListSpecifics& pb_entry) { |
| 267 if (!pb_entry.has_url()) { |
| 268 return nullptr; |
| 269 } |
| 270 GURL url(pb_entry.url()); |
| 271 if (url.is_empty() || !url.is_valid()) { |
| 272 return nullptr; |
| 273 } |
| 274 std::string title; |
| 275 if (pb_entry.has_title()) { |
| 276 title = pb_entry.title(); |
| 277 } |
| 278 |
| 279 int64_t creation_time_us = 0; |
| 280 if (pb_entry.has_creation_time_us()) { |
| 281 creation_time_us = pb_entry.creation_time_us(); |
| 282 } |
| 283 |
| 284 int64_t update_time_us = 0; |
| 285 if (pb_entry.has_update_time_us()) { |
| 286 update_time_us = pb_entry.update_time_us(); |
| 287 } |
| 288 |
| 289 return base::WrapUnique<ReadingListEntry>( |
| 290 new ReadingListEntry(url, title, creation_time_us, update_time_us, |
| 291 WAITING, base::FilePath(), 0, nullptr)); |
| 292 } |
| 293 |
| 294 void ReadingListEntry::MergeLocalStateFrom(ReadingListEntry& other) { |
| 295 distilled_path_ = std::move(other.distilled_path_); |
| 296 distilled_state_ = std::move(other.distilled_state_); |
| 297 backoff_ = std::move(other.backoff_); |
| 298 failed_download_counter_ = std::move(other.failed_download_counter_); |
| 299 } |
| 300 |
| 301 std::unique_ptr<reading_list::ReadingListLocal> |
| 302 ReadingListEntry::AsReadingListLocal(bool read) const { |
| 303 std::unique_ptr<reading_list::ReadingListLocal> pb_entry = |
| 304 base::MakeUnique<reading_list::ReadingListLocal>(); |
| 305 |
| 306 // URL is used as the key for the database and sync as there is only one entry |
| 307 // per URL. |
| 308 pb_entry->set_entry_id(URL().spec()); |
| 309 pb_entry->set_title(Title()); |
| 310 pb_entry->set_url(URL().spec()); |
| 311 pb_entry->set_creation_time_us(CreationTime()); |
| 312 pb_entry->set_update_time_us(UpdateTime()); |
| 313 |
| 314 if (read) { |
| 315 pb_entry->set_status(reading_list::ReadingListLocal::READ); |
| 316 } else { |
| 317 pb_entry->set_status(reading_list::ReadingListLocal::UNREAD); |
| 318 } |
| 319 |
| 320 reading_list::ReadingListLocal::DistillationState distilation_state; |
| 321 switch (DistilledState()) { |
| 322 case ReadingListEntry::WAITING: |
| 323 distilation_state = reading_list::ReadingListLocal::WAITING; |
| 324 break; |
| 325 case ReadingListEntry::PROCESSING: |
| 326 distilation_state = reading_list::ReadingListLocal::PROCESSING; |
| 327 break; |
| 328 case ReadingListEntry::PROCESSED: |
| 329 distilation_state = reading_list::ReadingListLocal::PROCESSED; |
| 330 break; |
| 331 case ReadingListEntry::WILL_RETRY: |
| 332 distilation_state = reading_list::ReadingListLocal::WILL_RETRY; |
| 333 break; |
| 334 case ReadingListEntry::ERROR: |
| 335 distilation_state = reading_list::ReadingListLocal::ERROR; |
| 336 break; |
| 337 } |
| 338 pb_entry->set_distillation_state(distilation_state); |
| 339 if (!DistilledPath().empty()) { |
| 340 pb_entry->set_distilled_path(DistilledPath().value()); |
| 341 } |
| 342 pb_entry->set_failed_download_counter(failed_download_counter_); |
| 343 |
| 344 if (backoff_) { |
| 345 std::unique_ptr<base::Value> backoff = |
| 346 net::BackoffEntrySerializer::SerializeToValue(*backoff_, |
| 347 base::Time::Now()); |
| 348 |
| 349 std::string output; |
| 350 JSONStringValueSerializer serializer(&output); |
| 351 serializer.Serialize(*backoff); |
| 352 pb_entry->set_backoff(output); |
| 353 } |
| 354 return pb_entry; |
| 355 } |
| 356 |
| 357 std::unique_ptr<sync_pb::ReadingListSpecifics> |
| 358 ReadingListEntry::AsReadingListSpecifics(bool read) const { |
| 359 std::unique_ptr<sync_pb::ReadingListSpecifics> pb_entry = |
| 360 base::MakeUnique<sync_pb::ReadingListSpecifics>(); |
| 361 |
| 362 // URL is used as the key for the database and sync as there is only one entry |
| 363 // per URL. |
| 364 pb_entry->set_entry_id(URL().spec()); |
| 365 pb_entry->set_title(Title()); |
| 366 pb_entry->set_url(URL().spec()); |
| 367 pb_entry->set_creation_time_us(CreationTime()); |
| 368 pb_entry->set_update_time_us(UpdateTime()); |
| 369 |
| 370 if (read) { |
| 371 pb_entry->set_status(sync_pb::ReadingListSpecifics::READ); |
| 372 } else { |
| 373 pb_entry->set_status(sync_pb::ReadingListSpecifics::UNREAD); |
| 374 } |
| 375 |
| 376 return pb_entry; |
| 377 } |
| 378 |
| 379 bool ReadingListEntry::CompareEntryUpdateTime(const ReadingListEntry& lhs, |
| 380 const ReadingListEntry& rhs) { |
| 381 return lhs.UpdateTime() > rhs.UpdateTime(); |
| 382 } |
| OLD | NEW |