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