| 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_model_impl.h" | 5 #include "ios/chrome/browser/reading_list/reading_list_model_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/logging.h" |
| 9 #include "base/memory/ptr_util.h" |
| 7 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 8 #include "components/prefs/pref_service.h" | 11 #include "components/prefs/pref_service.h" |
| 9 #include "ios/chrome/browser/reading_list/reading_list_model_storage.h" | 12 #include "ios/chrome/browser/reading_list/reading_list_model_storage.h" |
| 10 #include "ios/chrome/browser/reading_list/reading_list_pref_names.h" | 13 #include "ios/chrome/browser/reading_list/reading_list_pref_names.h" |
| 11 #include "url/gurl.h" | 14 #include "url/gurl.h" |
| 12 | 15 |
| 13 ReadingListModelImpl::ReadingListModelImpl() | 16 ReadingListModelImpl::ReadingListModelImpl() |
| 14 : ReadingListModelImpl(nullptr, nullptr) {} | 17 : ReadingListModelImpl(nullptr, nullptr) {} |
| 15 | 18 |
| 16 ReadingListModelImpl::ReadingListModelImpl( | 19 ReadingListModelImpl::ReadingListModelImpl( |
| 17 std::unique_ptr<ReadingListModelStorage> storage, | 20 std::unique_ptr<ReadingListModelStorage> storage, |
| 18 PrefService* pref_service) | 21 PrefService* pref_service) |
| 19 : pref_service_(pref_service), has_unseen_(false) { | 22 : pref_service_(pref_service), |
| 23 has_unseen_(false), |
| 24 loaded_(false), |
| 25 weak_ptr_factory_(this) { |
| 26 DCHECK(CalledOnValidThread()); |
| 20 if (storage) { | 27 if (storage) { |
| 21 storage_layer_ = std::move(storage); | 28 storage_layer_ = std::move(storage); |
| 22 read_ = storage_layer_->LoadPersistentReadList(); | 29 storage_layer_->SetReadingListModel(this, this); |
| 23 unread_ = storage_layer_->LoadPersistentUnreadList(); | 30 } else { |
| 24 has_unseen_ = GetPersistentHasUnseen(); | 31 loaded_ = true; |
| 32 read_ = base::MakeUnique<ReadingListEntries>(); |
| 33 unread_ = base::MakeUnique<ReadingListEntries>(); |
| 25 } | 34 } |
| 26 loaded_ = true; | 35 has_unseen_ = GetPersistentHasUnseen(); |
| 27 } | 36 } |
| 28 | 37 |
| 29 ReadingListModelImpl::~ReadingListModelImpl() {} | 38 ReadingListModelImpl::~ReadingListModelImpl() {} |
| 30 | 39 |
| 40 void ReadingListModelImpl::StoreLoaded( |
| 41 std::unique_ptr<ReadingListEntries> unread, |
| 42 std::unique_ptr<ReadingListEntries> read) { |
| 43 DCHECK(CalledOnValidThread()); |
| 44 read_ = std::move(read); |
| 45 unread_ = std::move(unread); |
| 46 loaded_ = true; |
| 47 SortEntries(); |
| 48 for (auto& observer : observers_) |
| 49 observer.ReadingListModelLoaded(this); |
| 50 } |
| 51 |
| 31 void ReadingListModelImpl::Shutdown() { | 52 void ReadingListModelImpl::Shutdown() { |
| 53 DCHECK(CalledOnValidThread()); |
| 32 for (auto& observer : observers_) | 54 for (auto& observer : observers_) |
| 33 observer.ReadingListModelBeingDeleted(this); | 55 observer.ReadingListModelBeingDeleted(this); |
| 34 loaded_ = false; | 56 loaded_ = false; |
| 35 } | 57 } |
| 36 | 58 |
| 37 bool ReadingListModelImpl::loaded() const { | 59 bool ReadingListModelImpl::loaded() const { |
| 60 DCHECK(CalledOnValidThread()); |
| 38 return loaded_; | 61 return loaded_; |
| 39 } | 62 } |
| 40 | 63 |
| 41 size_t ReadingListModelImpl::unread_size() const { | 64 size_t ReadingListModelImpl::unread_size() const { |
| 42 DCHECK(loaded()); | 65 DCHECK(CalledOnValidThread()); |
| 43 return unread_.size(); | 66 if (!loaded()) |
| 67 return 0; |
| 68 return unread_->size(); |
| 44 } | 69 } |
| 45 | 70 |
| 46 size_t ReadingListModelImpl::read_size() const { | 71 size_t ReadingListModelImpl::read_size() const { |
| 47 DCHECK(loaded()); | 72 DCHECK(CalledOnValidThread()); |
| 48 return read_.size(); | 73 if (!loaded()) |
| 74 return 0; |
| 75 return read_->size(); |
| 49 } | 76 } |
| 50 | 77 |
| 51 bool ReadingListModelImpl::HasUnseenEntries() const { | 78 bool ReadingListModelImpl::HasUnseenEntries() const { |
| 52 DCHECK(loaded()); | 79 DCHECK(CalledOnValidThread()); |
| 80 if (!loaded()) |
| 81 return false; |
| 53 return unread_size() && has_unseen_; | 82 return unread_size() && has_unseen_; |
| 54 } | 83 } |
| 55 | 84 |
| 56 void ReadingListModelImpl::ResetUnseenEntries() { | 85 void ReadingListModelImpl::ResetUnseenEntries() { |
| 86 DCHECK(CalledOnValidThread()); |
| 57 DCHECK(loaded()); | 87 DCHECK(loaded()); |
| 58 has_unseen_ = false; | 88 has_unseen_ = false; |
| 59 if (storage_layer_ && !IsPerformingBatchUpdates()) | 89 if (!IsPerformingBatchUpdates()) |
| 60 SetPersistentHasUnseen(false); | 90 SetPersistentHasUnseen(false); |
| 61 } | 91 } |
| 62 | 92 |
| 63 const ReadingListEntry& ReadingListModelImpl::GetUnreadEntryAtIndex( | 93 const ReadingListEntry& ReadingListModelImpl::GetUnreadEntryAtIndex( |
| 64 size_t index) const { | 94 size_t index) const { |
| 95 DCHECK(CalledOnValidThread()); |
| 65 DCHECK(loaded()); | 96 DCHECK(loaded()); |
| 66 return unread_[index]; | 97 return unread_->at(index); |
| 67 } | 98 } |
| 68 | 99 |
| 69 const ReadingListEntry& ReadingListModelImpl::GetReadEntryAtIndex( | 100 const ReadingListEntry& ReadingListModelImpl::GetReadEntryAtIndex( |
| 70 size_t index) const { | 101 size_t index) const { |
| 102 DCHECK(CalledOnValidThread()); |
| 71 DCHECK(loaded()); | 103 DCHECK(loaded()); |
| 72 return read_[index]; | 104 return read_->at(index); |
| 73 } | 105 } |
| 74 | 106 |
| 75 const ReadingListEntry* ReadingListModelImpl::GetEntryFromURL( | 107 const ReadingListEntry* ReadingListModelImpl::GetEntryFromURL( |
| 76 const GURL& gurl) const { | 108 const GURL& gurl, |
| 109 bool* read) const { |
| 110 DCHECK(CalledOnValidThread()); |
| 77 DCHECK(loaded()); | 111 DCHECK(loaded()); |
| 112 return GetMutableEntryFromURL(gurl, read); |
| 113 } |
| 114 |
| 115 ReadingListEntry* ReadingListModelImpl::GetMutableEntryFromURL( |
| 116 const GURL& gurl, |
| 117 bool* read) const { |
| 118 DCHECK(CalledOnValidThread()); |
| 119 DCHECK(loaded()); |
| 120 bool is_read; |
| 78 ReadingListEntry entry(gurl, std::string()); | 121 ReadingListEntry entry(gurl, std::string()); |
| 79 auto it = std::find(read_.begin(), read_.end(), entry); | 122 auto it = std::find(read_->begin(), read_->end(), entry); |
| 80 if (it == read_.end()) { | 123 is_read = true; |
| 81 it = std::find(unread_.begin(), unread_.end(), entry); | 124 if (it == read_->end()) { |
| 82 if (it == unread_.end()) | 125 it = std::find(unread_->begin(), unread_->end(), entry); |
| 126 is_read = false; |
| 127 if (it == unread_->end()) |
| 83 return nullptr; | 128 return nullptr; |
| 84 } | 129 } |
| 130 if (read) { |
| 131 *read = is_read; |
| 132 } |
| 85 return &(*it); | 133 return &(*it); |
| 86 } | 134 } |
| 87 | 135 |
| 88 bool ReadingListModelImpl::CallbackEntryURL( | 136 bool ReadingListModelImpl::CallbackEntryURL( |
| 89 const GURL& url, | 137 const GURL& url, |
| 90 base::Callback<void(const ReadingListEntry&)> callback) const { | 138 base::Callback<void(const ReadingListEntry&)> callback) const { |
| 139 DCHECK(CalledOnValidThread()); |
| 91 DCHECK(loaded()); | 140 DCHECK(loaded()); |
| 92 const ReadingListEntry* entry = GetEntryFromURL(url); | 141 const ReadingListEntry* entry = GetMutableEntryFromURL(url, nullptr); |
| 93 if (entry) { | 142 if (entry) { |
| 94 callback.Run(*entry); | 143 callback.Run(*entry); |
| 95 return true; | 144 return true; |
| 96 } | 145 } |
| 97 return false; | 146 return false; |
| 98 } | 147 } |
| 99 | 148 |
| 100 void ReadingListModelImpl::RemoveEntryByURL(const GURL& url) { | 149 void ReadingListModelImpl::MoveEntryFrom(ReadingListEntries* entries, |
| 150 const ReadingListEntry& entry, |
| 151 bool read) { |
| 152 auto result = std::find(entries->begin(), entries->end(), entry); |
| 153 DCHECK(result != entries->end()); |
| 154 int index = std::distance(entries->begin(), result); |
| 155 for (auto& observer : observers_) |
| 156 observer.ReadingListWillMoveEntry(this, index, read); |
| 157 entries->erase(result); |
| 158 } |
| 159 |
| 160 void ReadingListModelImpl::SyncAddEntry(std::unique_ptr<ReadingListEntry> entry, |
| 161 bool read) { |
| 162 DCHECK(CalledOnValidThread()); |
| 101 DCHECK(loaded()); | 163 DCHECK(loaded()); |
| 102 const ReadingListEntry entry(url, std::string()); | 164 DCHECK(storage_layer_); |
| 103 | 165 bool is_existing_entry_read; |
| 104 auto result = std::find(unread_.begin(), unread_.end(), entry); | 166 ReadingListEntry* existing_entry = |
| 105 if (result != unread_.end()) { | 167 GetMutableEntryFromURL(entry->URL(), &is_existing_entry_read); |
| 106 for (auto& observer : observers_) { | 168 if (!existing_entry) { |
| 107 observer.ReadingListWillRemoveUnreadEntry( | 169 storage_layer_->SaveEntry(*entry, read); |
| 108 this, std::distance(unread_.begin(), result)); | 170 if (read) { |
| 171 for (auto& observer : observers_) |
| 172 observer.ReadingListWillAddReadEntry(this, *entry); |
| 173 read_->insert(read_->begin(), std::move(*entry)); |
| 174 } else { |
| 175 for (auto& observer : observers_) |
| 176 observer.ReadingListWillAddUnreadEntry(this, *entry); |
| 177 has_unseen_ = true; |
| 178 SetPersistentHasUnseen(true); |
| 179 unread_->insert(unread_->begin(), std::move(*entry)); |
| 109 } | 180 } |
| 110 unread_.erase(result); | |
| 111 if (storage_layer_ && !IsPerformingBatchUpdates()) | |
| 112 storage_layer_->SavePersistentUnreadList(unread_); | |
| 113 for (auto& observer : observers_) | 181 for (auto& observer : observers_) |
| 114 observer.ReadingListDidApplyChanges(this); | 182 observer.ReadingListDidApplyChanges(this); |
| 115 return; | 183 return; |
| 116 } | 184 } |
| 117 | 185 |
| 118 result = std::find(read_.begin(), read_.end(), entry); | 186 if (existing_entry->UpdateTime() > entry->UpdateTime()) { |
| 119 if (result != read_.end()) { | 187 // Existing entry is newer than the sync one. Do not update it. |
| 120 for (auto& observer : observers_) { | 188 return; |
| 121 observer.ReadingListWillRemoveReadEntry( | 189 } |
| 122 this, std::distance(read_.begin(), result)); | 190 |
| 191 // Merge local data in new entry. |
| 192 entry->MergeLocalStateFrom(*existing_entry); |
| 193 |
| 194 if (is_existing_entry_read) { |
| 195 MoveEntryFrom(read_.get(), *existing_entry, true); |
| 196 } else { |
| 197 MoveEntryFrom(unread_.get(), *existing_entry, false); |
| 198 } |
| 199 |
| 200 storage_layer_->SaveEntry(*entry, read); |
| 201 |
| 202 if (read) { |
| 203 read_->push_back(std::move(*entry)); |
| 204 } else { |
| 205 unread_->push_back(std::move(*entry)); |
| 206 } |
| 207 for (auto& observer : observers_) |
| 208 observer.ReadingListDidApplyChanges(this); |
| 209 } |
| 210 |
| 211 void ReadingListModelImpl::SyncRemoveEntry(const GURL& gurl) { |
| 212 RemoveEntryByURL(gurl); |
| 213 } |
| 214 |
| 215 void ReadingListModelImpl::RemoveEntryByURL(const GURL& url) { |
| 216 DCHECK(CalledOnValidThread()); |
| 217 DCHECK(loaded()); |
| 218 const ReadingListEntry entry(url, std::string()); |
| 219 |
| 220 auto result = std::find(unread_->begin(), unread_->end(), entry); |
| 221 if (result != unread_->end()) { |
| 222 for (auto& observer : observers_) |
| 223 observer.ReadingListWillRemoveUnreadEntry( |
| 224 this, std::distance(unread_->begin(), result)); |
| 225 |
| 226 if (storage_layer_) { |
| 227 storage_layer_->RemoveEntry(*result); |
| 123 } | 228 } |
| 124 read_.erase(result); | 229 unread_->erase(result); |
| 125 if (storage_layer_ && !IsPerformingBatchUpdates()) | 230 |
| 126 storage_layer_->SavePersistentReadList(read_); | |
| 127 for (auto& observer : observers_) | 231 for (auto& observer : observers_) |
| 128 observer.ReadingListDidApplyChanges(this); | 232 observer.ReadingListDidApplyChanges(this); |
| 129 return; | 233 return; |
| 234 } |
| 235 |
| 236 result = std::find(read_->begin(), read_->end(), entry); |
| 237 if (result != read_->end()) { |
| 238 for (auto& observer : observers_) |
| 239 observer.ReadingListWillRemoveReadEntry( |
| 240 this, std::distance(read_->begin(), result)); |
| 241 if (storage_layer_) { |
| 242 storage_layer_->RemoveEntry(*result); |
| 243 } |
| 244 read_->erase(result); |
| 245 |
| 246 for (auto& observer : observers_) |
| 247 observer.ReadingListDidApplyChanges(this); |
| 248 return; |
| 130 } | 249 } |
| 131 } | 250 } |
| 132 | 251 |
| 133 const ReadingListEntry& ReadingListModelImpl::AddEntry( | 252 const ReadingListEntry& ReadingListModelImpl::AddEntry( |
| 134 const GURL& url, | 253 const GURL& url, |
| 135 const std::string& title) { | 254 const std::string& title) { |
| 255 DCHECK(CalledOnValidThread()); |
| 136 DCHECK(loaded()); | 256 DCHECK(loaded()); |
| 137 RemoveEntryByURL(url); | 257 RemoveEntryByURL(url); |
| 138 | 258 |
| 139 std::string trimmedTitle(title); | 259 std::string trimmedTitle(title); |
| 140 base::TrimWhitespaceASCII(trimmedTitle, base::TRIM_ALL, &trimmedTitle); | 260 base::TrimWhitespaceASCII(trimmedTitle, base::TRIM_ALL, &trimmedTitle); |
| 141 | 261 |
| 142 ReadingListEntry entry(url, trimmedTitle); | 262 ReadingListEntry entry(url, trimmedTitle); |
| 143 for (auto& observer : observers_) | 263 for (auto& observer : observers_) |
| 144 observer.ReadingListWillAddUnreadEntry(this, entry); | 264 observer.ReadingListWillAddUnreadEntry(this, entry); |
| 145 unread_.insert(unread_.begin(), std::move(entry)); | |
| 146 has_unseen_ = true; | 265 has_unseen_ = true; |
| 147 if (storage_layer_ && !IsPerformingBatchUpdates()) { | 266 SetPersistentHasUnseen(true); |
| 148 storage_layer_->SavePersistentUnreadList(unread_); | 267 if (storage_layer_) { |
| 149 SetPersistentHasUnseen(true); | 268 storage_layer_->SaveEntry(entry, false); |
| 150 } | 269 } |
| 270 unread_->insert(unread_->begin(), std::move(entry)); |
| 271 |
| 151 for (auto& observer : observers_) | 272 for (auto& observer : observers_) |
| 152 observer.ReadingListDidApplyChanges(this); | 273 observer.ReadingListDidApplyChanges(this); |
| 153 return *unread_.begin(); | 274 return *unread_->begin(); |
| 154 } | 275 } |
| 155 | 276 |
| 156 void ReadingListModelImpl::MarkUnreadByURL(const GURL& url) { | 277 void ReadingListModelImpl::MarkUnreadByURL(const GURL& url) { |
| 278 DCHECK(CalledOnValidThread()); |
| 157 DCHECK(loaded()); | 279 DCHECK(loaded()); |
| 158 ReadingListEntry entry(url, std::string()); | 280 ReadingListEntry entry(url, std::string()); |
| 159 auto result = std::find(read_.begin(), read_.end(), entry); | 281 auto result = std::find(read_->begin(), read_->end(), entry); |
| 160 if (result == read_.end()) | 282 if (result == read_->end()) |
| 161 return; | 283 return; |
| 162 | 284 |
| 163 for (ReadingListModelObserver& observer : observers_) { | 285 for (ReadingListModelObserver& observer : observers_) { |
| 164 observer.ReadingListWillMoveEntry(this, | 286 observer.ReadingListWillMoveEntry( |
| 165 std::distance(read_.begin(), result)); | 287 this, std::distance(read_->begin(), result), true); |
| 166 } | 288 } |
| 167 | 289 |
| 168 unread_.insert(unread_.begin(), std::move(*result)); | 290 result->MarkEntryUpdated(); |
| 169 read_.erase(result); | 291 if (storage_layer_) { |
| 292 storage_layer_->SaveEntry(*result, false); |
| 293 } |
| 170 | 294 |
| 171 if (storage_layer_ && !IsPerformingBatchUpdates()) { | 295 unread_->insert(unread_->begin(), std::move(*result)); |
| 172 storage_layer_->SavePersistentUnreadList(read_); | 296 read_->erase(result); |
| 173 storage_layer_->SavePersistentReadList(unread_); | 297 |
| 174 } | |
| 175 for (ReadingListModelObserver& observer : observers_) { | 298 for (ReadingListModelObserver& observer : observers_) { |
| 176 observer.ReadingListDidApplyChanges(this); | 299 observer.ReadingListDidApplyChanges(this); |
| 177 } | 300 } |
| 178 } | 301 } |
| 179 | 302 |
| 180 void ReadingListModelImpl::MarkReadByURL(const GURL& url) { | 303 void ReadingListModelImpl::MarkReadByURL(const GURL& url) { |
| 304 DCHECK(CalledOnValidThread()); |
| 181 DCHECK(loaded()); | 305 DCHECK(loaded()); |
| 182 ReadingListEntry entry(url, std::string()); | 306 ReadingListEntry entry(url, std::string()); |
| 183 auto result = std::find(unread_.begin(), unread_.end(), entry); | 307 auto result = std::find(unread_->begin(), unread_->end(), entry); |
| 184 if (result == unread_.end()) | 308 if (result == unread_->end()) |
| 185 return; | 309 return; |
| 186 | 310 |
| 187 for (auto& observer : observers_) { | 311 for (auto& observer : observers_) |
| 188 observer.ReadingListWillMoveEntry(this, | 312 observer.ReadingListWillMoveEntry( |
| 189 std::distance(unread_.begin(), result)); | 313 this, std::distance(unread_->begin(), result), false); |
| 314 |
| 315 result->MarkEntryUpdated(); |
| 316 if (storage_layer_) { |
| 317 storage_layer_->SaveEntry(*result, true); |
| 190 } | 318 } |
| 191 | 319 |
| 192 read_.insert(read_.begin(), std::move(*result)); | 320 read_->insert(read_->begin(), std::move(*result)); |
| 193 unread_.erase(result); | 321 unread_->erase(result); |
| 194 | 322 |
| 195 if (storage_layer_ && !IsPerformingBatchUpdates()) { | |
| 196 storage_layer_->SavePersistentUnreadList(unread_); | |
| 197 storage_layer_->SavePersistentReadList(read_); | |
| 198 } | |
| 199 for (auto& observer : observers_) | 323 for (auto& observer : observers_) |
| 200 observer.ReadingListDidApplyChanges(this); | 324 observer.ReadingListDidApplyChanges(this); |
| 201 } | 325 } |
| 202 | 326 |
| 203 void ReadingListModelImpl::SetEntryTitle(const GURL& url, | 327 void ReadingListModelImpl::SetEntryTitle(const GURL& url, |
| 204 const std::string& title) { | 328 const std::string& title) { |
| 329 DCHECK(CalledOnValidThread()); |
| 205 DCHECK(loaded()); | 330 DCHECK(loaded()); |
| 206 const ReadingListEntry entry(url, std::string()); | 331 const ReadingListEntry entry(url, std::string()); |
| 207 | 332 |
| 208 auto result = std::find(unread_.begin(), unread_.end(), entry); | 333 auto result = std::find(unread_->begin(), unread_->end(), entry); |
| 209 if (result != unread_.end()) { | 334 if (result != unread_->end()) { |
| 210 for (auto& observer : observers_) { | 335 for (auto& observer : observers_) |
| 211 observer.ReadingListWillUpdateUnreadEntry( | 336 observer.ReadingListWillUpdateUnreadEntry( |
| 212 this, std::distance(unread_.begin(), result)); | 337 this, std::distance(unread_->begin(), result)); |
| 338 result->SetTitle(title); |
| 339 |
| 340 if (storage_layer_) { |
| 341 storage_layer_->SaveEntry(*result, false); |
| 213 } | 342 } |
| 214 result->SetTitle(title); | |
| 215 if (storage_layer_ && !IsPerformingBatchUpdates()) | |
| 216 storage_layer_->SavePersistentUnreadList(unread_); | |
| 217 for (auto& observer : observers_) | 343 for (auto& observer : observers_) |
| 218 observer.ReadingListDidApplyChanges(this); | 344 observer.ReadingListDidApplyChanges(this); |
| 219 return; | 345 return; |
| 220 } | 346 } |
| 221 | 347 |
| 222 result = std::find(read_.begin(), read_.end(), entry); | 348 result = std::find(read_->begin(), read_->end(), entry); |
| 223 if (result != read_.end()) { | 349 if (result != read_->end()) { |
| 224 for (auto& observer : observers_) { | 350 for (auto& observer : observers_) |
| 225 observer.ReadingListWillUpdateReadEntry( | 351 observer.ReadingListWillUpdateReadEntry( |
| 226 this, std::distance(read_.begin(), result)); | 352 this, std::distance(read_->begin(), result)); |
| 353 result->SetTitle(title); |
| 354 if (storage_layer_) { |
| 355 storage_layer_->SaveEntry(*result, true); |
| 227 } | 356 } |
| 228 result->SetTitle(title); | |
| 229 if (storage_layer_ && !IsPerformingBatchUpdates()) | |
| 230 storage_layer_->SavePersistentReadList(read_); | |
| 231 for (auto& observer : observers_) | 357 for (auto& observer : observers_) |
| 232 observer.ReadingListDidApplyChanges(this); | 358 observer.ReadingListDidApplyChanges(this); |
| 233 return; | 359 return; |
| 234 } | 360 } |
| 235 } | 361 } |
| 236 | 362 |
| 237 void ReadingListModelImpl::SetEntryDistilledURL(const GURL& url, | 363 void ReadingListModelImpl::SetEntryDistilledURL(const GURL& url, |
| 238 const GURL& distilled_url) { | 364 const GURL& distilled_url) { |
| 365 DCHECK(CalledOnValidThread()); |
| 239 DCHECK(loaded()); | 366 DCHECK(loaded()); |
| 240 const ReadingListEntry entry(url, std::string()); | 367 const ReadingListEntry entry(url, std::string()); |
| 241 | 368 |
| 242 auto result = std::find(unread_.begin(), unread_.end(), entry); | 369 auto result = std::find(unread_->begin(), unread_->end(), entry); |
| 243 if (result != unread_.end()) { | 370 if (result != unread_->end()) { |
| 244 for (auto& observer : observers_) { | 371 for (auto& observer : observers_) |
| 245 observer.ReadingListWillUpdateUnreadEntry( | 372 observer.ReadingListWillUpdateUnreadEntry( |
| 246 this, std::distance(unread_.begin(), result)); | 373 this, std::distance(unread_->begin(), result)); |
| 374 result->SetDistilledURL(distilled_url); |
| 375 if (storage_layer_) { |
| 376 storage_layer_->SaveEntry(*result, false); |
| 247 } | 377 } |
| 248 result->SetDistilledURL(distilled_url); | |
| 249 if (storage_layer_ && !IsPerformingBatchUpdates()) | |
| 250 storage_layer_->SavePersistentUnreadList(unread_); | |
| 251 for (auto& observer : observers_) | 378 for (auto& observer : observers_) |
| 252 observer.ReadingListDidApplyChanges(this); | 379 observer.ReadingListDidApplyChanges(this); |
| 253 return; | 380 return; |
| 254 } | 381 } |
| 255 | 382 |
| 256 result = std::find(read_.begin(), read_.end(), entry); | 383 result = std::find(read_->begin(), read_->end(), entry); |
| 257 if (result != read_.end()) { | 384 if (result != read_->end()) { |
| 258 for (auto& observer : observers_) { | 385 for (auto& observer : observers_) |
| 259 observer.ReadingListWillUpdateReadEntry( | 386 observer.ReadingListWillUpdateReadEntry( |
| 260 this, std::distance(read_.begin(), result)); | 387 this, std::distance(read_->begin(), result)); |
| 388 result->SetDistilledURL(distilled_url); |
| 389 if (storage_layer_) { |
| 390 storage_layer_->SaveEntry(*result, true); |
| 261 } | 391 } |
| 262 result->SetDistilledURL(distilled_url); | |
| 263 if (storage_layer_ && !IsPerformingBatchUpdates()) | |
| 264 storage_layer_->SavePersistentReadList(read_); | |
| 265 for (auto& observer : observers_) | 392 for (auto& observer : observers_) |
| 266 observer.ReadingListDidApplyChanges(this); | 393 observer.ReadingListDidApplyChanges(this); |
| 267 return; | 394 return; |
| 268 } | 395 } |
| 269 } | 396 } |
| 270 | 397 |
| 271 void ReadingListModelImpl::SetEntryDistilledState( | 398 void ReadingListModelImpl::SetEntryDistilledState( |
| 272 const GURL& url, | 399 const GURL& url, |
| 273 ReadingListEntry::DistillationState state) { | 400 ReadingListEntry::DistillationState state) { |
| 401 DCHECK(CalledOnValidThread()); |
| 274 DCHECK(loaded()); | 402 DCHECK(loaded()); |
| 275 const ReadingListEntry entry(url, std::string()); | 403 const ReadingListEntry entry(url, std::string()); |
| 276 | 404 |
| 277 auto result = std::find(unread_.begin(), unread_.end(), entry); | 405 auto result = std::find(unread_->begin(), unread_->end(), entry); |
| 278 if (result != unread_.end()) { | 406 if (result != unread_->end()) { |
| 279 for (auto& observer : observers_) { | 407 for (auto& observer : observers_) |
| 280 observer.ReadingListWillUpdateUnreadEntry( | 408 observer.ReadingListWillUpdateUnreadEntry( |
| 281 this, std::distance(unread_.begin(), result)); | 409 this, std::distance(unread_->begin(), result)); |
| 410 result->SetDistilledState(state); |
| 411 if (storage_layer_) { |
| 412 storage_layer_->SaveEntry(*result, false); |
| 282 } | 413 } |
| 283 result->SetDistilledState(state); | |
| 284 if (storage_layer_ && !IsPerformingBatchUpdates()) | |
| 285 storage_layer_->SavePersistentUnreadList(unread_); | |
| 286 for (auto& observer : observers_) | 414 for (auto& observer : observers_) |
| 287 observer.ReadingListDidApplyChanges(this); | 415 observer.ReadingListDidApplyChanges(this); |
| 288 return; | 416 return; |
| 289 } | 417 } |
| 290 | 418 |
| 291 result = std::find(read_.begin(), read_.end(), entry); | 419 result = std::find(read_->begin(), read_->end(), entry); |
| 292 if (result != read_.end()) { | 420 if (result != read_->end()) { |
| 293 for (auto& observer : observers_) { | 421 for (auto& observer : observers_) |
| 294 observer.ReadingListWillUpdateReadEntry( | 422 observer.ReadingListWillUpdateReadEntry( |
| 295 this, std::distance(read_.begin(), result)); | 423 this, std::distance(read_->begin(), result)); |
| 424 result->SetDistilledState(state); |
| 425 if (storage_layer_) { |
| 426 storage_layer_->SaveEntry(*result, true); |
| 296 } | 427 } |
| 297 result->SetDistilledState(state); | |
| 298 if (storage_layer_ && !IsPerformingBatchUpdates()) | |
| 299 storage_layer_->SavePersistentReadList(read_); | |
| 300 for (auto& observer : observers_) | 428 for (auto& observer : observers_) |
| 301 observer.ReadingListDidApplyChanges(this); | 429 observer.ReadingListDidApplyChanges(this); |
| 302 return; | 430 return; |
| 303 } | 431 } |
| 304 }; | 432 }; |
| 305 | 433 |
| 306 void ReadingListModelImpl::EndBatchUpdates() { | 434 std::unique_ptr<ReadingListModel::ScopedReadingListBatchUpdate> |
| 307 ReadingListModel::EndBatchUpdates(); | 435 ReadingListModelImpl::CreateBatchToken() { |
| 308 if (IsPerformingBatchUpdates() || !storage_layer_) { | 436 return base::MakeUnique<ReadingListModelImpl::ScopedReadingListBatchUpdate>( |
| 309 return; | 437 this); |
| 438 } |
| 439 |
| 440 ReadingListModelImpl::ScopedReadingListBatchUpdate:: |
| 441 ScopedReadingListBatchUpdate(ReadingListModelImpl* model) |
| 442 : ReadingListModel::ScopedReadingListBatchUpdate:: |
| 443 ScopedReadingListBatchUpdate(model) { |
| 444 if (model->StorageLayer()) { |
| 445 storage_token_ = model->StorageLayer()->EnsureBatchCreated(); |
| 310 } | 446 } |
| 311 storage_layer_->SavePersistentUnreadList(unread_); | 447 } |
| 312 storage_layer_->SavePersistentReadList(read_); | 448 |
| 313 SetPersistentHasUnseen(has_unseen_); | 449 ReadingListModelImpl::ScopedReadingListBatchUpdate:: |
| 450 ~ScopedReadingListBatchUpdate() { |
| 451 storage_token_.reset(); |
| 452 } |
| 453 |
| 454 void ReadingListModelImpl::LeavingBatchUpdates() { |
| 455 DCHECK(CalledOnValidThread()); |
| 456 if (storage_layer_) { |
| 457 SetPersistentHasUnseen(has_unseen_); |
| 458 SortEntries(); |
| 459 } |
| 460 ReadingListModel::LeavingBatchUpdates(); |
| 461 } |
| 462 |
| 463 void ReadingListModelImpl::EnteringBatchUpdates() { |
| 464 DCHECK(CalledOnValidThread()); |
| 465 ReadingListModel::EnteringBatchUpdates(); |
| 314 } | 466 } |
| 315 | 467 |
| 316 void ReadingListModelImpl::SetPersistentHasUnseen(bool has_unseen) { | 468 void ReadingListModelImpl::SetPersistentHasUnseen(bool has_unseen) { |
| 469 DCHECK(CalledOnValidThread()); |
| 317 if (!pref_service_) { | 470 if (!pref_service_) { |
| 318 return; | 471 return; |
| 319 } | 472 } |
| 320 pref_service_->SetBoolean(reading_list::prefs::kReadingListHasUnseenEntries, | 473 pref_service_->SetBoolean(reading_list::prefs::kReadingListHasUnseenEntries, |
| 321 has_unseen); | 474 has_unseen); |
| 322 } | 475 } |
| 323 | 476 |
| 324 bool ReadingListModelImpl::GetPersistentHasUnseen() { | 477 bool ReadingListModelImpl::GetPersistentHasUnseen() { |
| 478 DCHECK(CalledOnValidThread()); |
| 325 if (!pref_service_) { | 479 if (!pref_service_) { |
| 326 return false; | 480 return false; |
| 327 } | 481 } |
| 328 return pref_service_->GetBoolean( | 482 return pref_service_->GetBoolean( |
| 329 reading_list::prefs::kReadingListHasUnseenEntries); | 483 reading_list::prefs::kReadingListHasUnseenEntries); |
| 330 } | 484 } |
| 485 |
| 486 syncer::ModelTypeSyncBridge* ReadingListModelImpl::GetModelTypeSyncBridge() { |
| 487 DCHECK(loaded()); |
| 488 if (!storage_layer_) |
| 489 return nullptr; |
| 490 return storage_layer_->GetModelTypeSyncBridge(); |
| 491 } |
| 492 |
| 493 void ReadingListModelImpl::SortEntries() { |
| 494 DCHECK(CalledOnValidThread()); |
| 495 DCHECK(loaded()); |
| 496 std::sort(read_->begin(), read_->end(), |
| 497 ReadingListEntry::CompareEntryUpdateTime); |
| 498 std::sort(unread_->begin(), unread_->end(), |
| 499 ReadingListEntry::CompareEntryUpdateTime); |
| 500 } |
| 501 |
| 502 ReadingListModelStorage* ReadingListModelImpl::StorageLayer() { |
| 503 return storage_layer_.get(); |
| 504 } |
| OLD | NEW |