Index: ios/chrome/browser/reading_list/reading_list_model_impl.cc |
diff --git a/ios/chrome/browser/reading_list/reading_list_model_impl.cc b/ios/chrome/browser/reading_list/reading_list_model_impl.cc |
index c3e068d65f0249a30a6ce1c36dbd381cdf56d260..4bc65bde49b5bbb6d4121e6ac9ea0c856fd2a720 100644 |
--- a/ios/chrome/browser/reading_list/reading_list_model_impl.cc |
+++ b/ios/chrome/browser/reading_list/reading_list_model_impl.cc |
@@ -4,82 +4,119 @@ |
#include "ios/chrome/browser/reading_list/reading_list_model_impl.h" |
+#include "base/bind.h" |
+#include "base/logging.h" |
+#include "base/memory/ptr_util.h" |
+#include "components/prefs/pref_service.h" |
#include "ios/chrome/browser/reading_list/reading_list_model_storage.h" |
+#include "ios/chrome/browser/reading_list/reading_list_pref_names.h" |
+#include "ios/web/public/web_thread.h" |
#include "url/gurl.h" |
-ReadingListModelImpl::ReadingListModelImpl() : ReadingListModelImpl(NULL) {} |
+ReadingListModelImpl::ReadingListModelImpl() |
+ : ReadingListModelImpl(NULL, NULL) {} |
ReadingListModelImpl::ReadingListModelImpl( |
- std::unique_ptr<ReadingListModelStorage> storage) |
- : hasUnseen_(false) { |
+ std::unique_ptr<ReadingListModelStorage> storage, |
+ PrefService* pref_service) |
+ : pref_service_(pref_service), |
+ has_unseen_(false), |
+ loaded_(false), |
+ weak_ptr_factory_(this) { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
if (storage) { |
- storageLayer_ = std::move(storage); |
- read_ = storageLayer_->LoadPersistentReadList(); |
- unread_ = storageLayer_->LoadPersistentUnreadList(); |
- hasUnseen_ = storageLayer_->LoadPersistentHasUnseen(); |
+ storage_layer_ = std::move(storage); |
+ storage_layer_->SetReadingListModel(this); |
+ storage_layer_->LoadPersistentLists(); |
+ } else { |
+ loaded_ = true; |
+ read_ = base::MakeUnique<ReadingListEntries>(); |
+ unread_ = base::MakeUnique<ReadingListEntries>(); |
} |
- loaded_ = true; |
+ has_unseen_ = LoadPersistentHasUnseen(); |
} |
ReadingListModelImpl::~ReadingListModelImpl() {} |
+void ReadingListModelImpl::ModelLoaded( |
+ std::unique_ptr<ReadingListEntries> unread, |
+ std::unique_ptr<ReadingListEntries> read) { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
+ read_ = std::move(read); |
+ unread_ = std::move(unread); |
+ loaded_ = true; |
+ FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
+ ReadingListModelLoaded(this)); |
+} |
+ |
void ReadingListModelImpl::Shutdown() { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListModelBeingDeleted(this)); |
loaded_ = false; |
} |
bool ReadingListModelImpl::loaded() const { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
return loaded_; |
} |
size_t ReadingListModelImpl::unread_size() const { |
- DCHECK(loaded()); |
- return unread_.size(); |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
+ if (!loaded()) |
+ return 0; |
+ return unread_->size(); |
} |
size_t ReadingListModelImpl::read_size() const { |
- DCHECK(loaded()); |
- return read_.size(); |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
+ if (!loaded()) |
+ return 0; |
+ return read_->size(); |
} |
bool ReadingListModelImpl::HasUnseenEntries() const { |
- DCHECK(loaded()); |
- return unread_size() && hasUnseen_; |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
+ if (!loaded()) |
+ return false; |
+ return unread_size() && has_unseen_; |
} |
void ReadingListModelImpl::ResetUnseenEntries() { |
DCHECK(loaded()); |
- hasUnseen_ = false; |
- if (storageLayer_ && !IsPerformingBatchUpdates()) |
- storageLayer_->SavePersistentHasUnseen(false); |
+ has_unseen_ = false; |
+ if (!IsPerformingBatchUpdates()) |
+ SavePersistentHasUnseen(false); |
} |
// Returns a specific entry. |
const ReadingListEntry& ReadingListModelImpl::GetUnreadEntryAtIndex( |
size_t index) const { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
DCHECK(loaded()); |
- return unread_[index]; |
+ return unread_->at(index); |
} |
const ReadingListEntry& ReadingListModelImpl::GetReadEntryAtIndex( |
size_t index) const { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
DCHECK(loaded()); |
- return read_[index]; |
+ return read_->at(index); |
} |
bool ReadingListModelImpl::CallbackEntryURL( |
const GURL& url, |
base::Callback<void(const ReadingListEntry&)> callback) const { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
DCHECK(loaded()); |
ReadingListEntry entry(url, std::string()); |
- auto resultUnread = std::find(unread_.begin(), unread_.end(), entry); |
- if (resultUnread != unread_.end()) { |
+ auto resultUnread = std::find(unread_->begin(), unread_->end(), entry); |
+ if (resultUnread != unread_->end()) { |
callback.Run(*resultUnread); |
return true; |
} |
- auto resultRead = std::find(read_.begin(), read_.end(), entry); |
- if (resultRead != read_.end()) { |
+ auto resultRead = std::find(read_->begin(), read_->end(), entry); |
+ if (resultRead != read_->end()) { |
callback.Run(*resultRead); |
return true; |
} |
@@ -87,30 +124,37 @@ bool ReadingListModelImpl::CallbackEntryURL( |
} |
void ReadingListModelImpl::RemoveEntryByUrl(const GURL& url) { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
DCHECK(loaded()); |
const ReadingListEntry entry(url, std::string()); |
- auto result = std::find(unread_.begin(), unread_.end(), entry); |
- if (result != unread_.end()) { |
+ auto result = std::find(unread_->begin(), unread_->end(), entry); |
+ if (result != unread_->end()) { |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListWillRemoveUnreadEntry( |
- this, std::distance(unread_.begin(), result))); |
- unread_.erase(result); |
- if (storageLayer_ && !IsPerformingBatchUpdates()) |
- storageLayer_->SavePersistentUnreadList(unread_); |
+ this, std::distance(unread_->begin(), result))); |
+ unread_->erase(result); |
+ |
+ if (storage_layer_) { |
+ storage_layer_->RemoveEntry(*result); |
+ } |
+ |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListDidApplyChanges(this)); |
return; |
} |
- result = std::find(read_.begin(), read_.end(), entry); |
- if (result != read_.end()) { |
+ result = std::find(read_->begin(), read_->end(), entry); |
+ if (result != read_->end()) { |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListWillRemoveReadEntry( |
- this, std::distance(read_.begin(), result))); |
- read_.erase(result); |
- if (storageLayer_ && !IsPerformingBatchUpdates()) |
- storageLayer_->SavePersistentReadList(read_); |
+ this, std::distance(read_->begin(), result))); |
+ read_->erase(result); |
+ |
+ if (storage_layer_) { |
+ storage_layer_->RemoveEntry(*result); |
+ } |
+ |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListDidApplyChanges(this)); |
return; |
@@ -120,70 +164,78 @@ void ReadingListModelImpl::RemoveEntryByUrl(const GURL& url) { |
const ReadingListEntry& ReadingListModelImpl::AddEntry( |
const GURL& url, |
const std::string& title) { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
DCHECK(loaded()); |
RemoveEntryByUrl(url); |
ReadingListEntry entry(url, title); |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListWillAddUnreadEntry(this, entry)); |
- unread_.insert(unread_.begin(), std::move(entry)); |
- hasUnseen_ = true; |
- if (storageLayer_ && !IsPerformingBatchUpdates()) { |
- storageLayer_->SavePersistentUnreadList(unread_); |
- storageLayer_->SavePersistentHasUnseen(true); |
+ has_unseen_ = true; |
+ SavePersistentHasUnseen(true); |
+ if (storage_layer_) { |
+ storage_layer_->SaveEntry(entry, false); |
} |
+ unread_->insert(unread_->begin(), std::move(entry)); |
+ |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListDidApplyChanges(this)); |
- return *unread_.begin(); |
+ return *unread_->begin(); |
} |
void ReadingListModelImpl::MarkReadByURL(const GURL& url) { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
DCHECK(loaded()); |
ReadingListEntry entry(url, std::string()); |
- auto result = std::find(unread_.begin(), unread_.end(), entry); |
- if (result == unread_.end()) |
+ auto result = std::find(unread_->begin(), unread_->end(), entry); |
+ if (result == unread_->end()) |
return; |
FOR_EACH_OBSERVER( |
ReadingListModelObserver, observers_, |
- ReadingListWillMoveEntry(this, std::distance(unread_.begin(), result))); |
+ ReadingListWillMoveEntry(this, std::distance(unread_->begin(), result))); |
- read_.insert(read_.begin(), std::move(*result)); |
- unread_.erase(result); |
- |
- if (storageLayer_ && !IsPerformingBatchUpdates()) { |
- storageLayer_->SavePersistentUnreadList(unread_); |
- storageLayer_->SavePersistentReadList(read_); |
+ result->MarkEntryUpdated(); |
+ if (storage_layer_) { |
+ storage_layer_->SaveEntry(*result, true); |
} |
+ |
+ read_->insert(read_->begin(), std::move(*result)); |
+ unread_->erase(result); |
+ |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListDidApplyChanges(this)); |
} |
void ReadingListModelImpl::SetEntryTitle(const GURL& url, |
const std::string& title) { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
DCHECK(loaded()); |
const ReadingListEntry entry(url, std::string()); |
- auto result = std::find(unread_.begin(), unread_.end(), entry); |
- if (result != unread_.end()) { |
+ auto result = std::find(unread_->begin(), unread_->end(), entry); |
+ if (result != unread_->end()) { |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListWillUpdateUnreadEntry( |
- this, std::distance(unread_.begin(), result))); |
+ this, std::distance(unread_->begin(), result))); |
result->SetTitle(title); |
- if (storageLayer_ && !IsPerformingBatchUpdates()) |
- storageLayer_->SavePersistentUnreadList(unread_); |
+ |
+ if (storage_layer_) { |
+ storage_layer_->SaveEntry(*result, false); |
+ } |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListDidApplyChanges(this)); |
return; |
} |
- result = std::find(read_.begin(), read_.end(), entry); |
- if (result != read_.end()) { |
+ result = std::find(read_->begin(), read_->end(), entry); |
+ if (result != read_->end()) { |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListWillUpdateReadEntry( |
- this, std::distance(read_.begin(), result))); |
+ this, std::distance(read_->begin(), result))); |
result->SetTitle(title); |
- if (storageLayer_ && !IsPerformingBatchUpdates()) |
- storageLayer_->SavePersistentReadList(read_); |
+ if (storage_layer_) { |
+ storage_layer_->SaveEntry(*result, true); |
+ } |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListDidApplyChanges(this)); |
return; |
@@ -192,30 +244,33 @@ void ReadingListModelImpl::SetEntryTitle(const GURL& url, |
void ReadingListModelImpl::SetEntryDistilledURL(const GURL& url, |
const GURL& distilled_url) { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
DCHECK(loaded()); |
const ReadingListEntry entry(url, std::string()); |
- auto result = std::find(unread_.begin(), unread_.end(), entry); |
- if (result != unread_.end()) { |
+ auto result = std::find(unread_->begin(), unread_->end(), entry); |
+ if (result != unread_->end()) { |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListWillUpdateUnreadEntry( |
- this, std::distance(unread_.begin(), result))); |
+ this, std::distance(unread_->begin(), result))); |
result->SetDistilledURL(distilled_url); |
- if (storageLayer_ && !IsPerformingBatchUpdates()) |
- storageLayer_->SavePersistentUnreadList(unread_); |
+ if (storage_layer_) { |
+ storage_layer_->SaveEntry(*result, false); |
+ } |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListDidApplyChanges(this)); |
return; |
} |
- result = std::find(read_.begin(), read_.end(), entry); |
- if (result != read_.end()) { |
+ result = std::find(read_->begin(), read_->end(), entry); |
+ if (result != read_->end()) { |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListWillUpdateReadEntry( |
- this, std::distance(read_.begin(), result))); |
+ this, std::distance(read_->begin(), result))); |
result->SetDistilledURL(distilled_url); |
- if (storageLayer_ && !IsPerformingBatchUpdates()) |
- storageLayer_->SavePersistentReadList(read_); |
+ if (storage_layer_) { |
+ storage_layer_->SaveEntry(*result, true); |
+ } |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListDidApplyChanges(this)); |
return; |
@@ -225,42 +280,70 @@ void ReadingListModelImpl::SetEntryDistilledURL(const GURL& url, |
void ReadingListModelImpl::SetEntryDistilledState( |
const GURL& url, |
ReadingListEntry::DistillationState state) { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
DCHECK(loaded()); |
const ReadingListEntry entry(url, std::string()); |
- auto result = std::find(unread_.begin(), unread_.end(), entry); |
- if (result != unread_.end()) { |
+ auto result = std::find(unread_->begin(), unread_->end(), entry); |
+ if (result != unread_->end()) { |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListWillUpdateUnreadEntry( |
- this, std::distance(unread_.begin(), result))); |
+ this, std::distance(unread_->begin(), result))); |
result->SetDistilledState(state); |
- if (storageLayer_ && !IsPerformingBatchUpdates()) |
- storageLayer_->SavePersistentUnreadList(unread_); |
+ if (storage_layer_) { |
+ storage_layer_->SaveEntry(*result, false); |
+ } |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListDidApplyChanges(this)); |
return; |
} |
- result = std::find(read_.begin(), read_.end(), entry); |
- if (result != read_.end()) { |
+ result = std::find(read_->begin(), read_->end(), entry); |
+ if (result != read_->end()) { |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListWillUpdateReadEntry( |
- this, std::distance(read_.begin(), result))); |
+ this, std::distance(read_->begin(), result))); |
result->SetDistilledState(state); |
- if (storageLayer_ && !IsPerformingBatchUpdates()) |
- storageLayer_->SavePersistentReadList(read_); |
+ if (storage_layer_) { |
+ storage_layer_->SaveEntry(*result, true); |
+ } |
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
ReadingListDidApplyChanges(this)); |
return; |
} |
}; |
-void ReadingListModelImpl::EndBatchUpdates() { |
- ReadingListModel::EndBatchUpdates(); |
- if (IsPerformingBatchUpdates() || !storageLayer_) { |
+void ReadingListModelImpl::LeavingBatchUpdates() { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
+ ReadingListModel::LeavingBatchUpdates(); |
+ if (storage_layer_) { |
+ SavePersistentHasUnseen(has_unseen_); |
+ storage_layer_->CommitTransaction(); |
+ } |
+} |
+ |
+void ReadingListModelImpl::EnteringBatchUpdates() { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
+ if (storage_layer_) { |
+ storage_layer_->BeginTransaction(); |
+ } |
+ ReadingListModel::EnteringBatchUpdates(); |
+} |
+ |
+void ReadingListModelImpl::SavePersistentHasUnseen(bool has_unseen) { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
+ if (!pref_service_) { |
return; |
} |
- storageLayer_->SavePersistentUnreadList(unread_); |
- storageLayer_->SavePersistentReadList(read_); |
- storageLayer_->SavePersistentHasUnseen(hasUnseen_); |
+ pref_service_->SetBoolean(reading_list::prefs::kReadingListHasUnseenEntries, |
+ has_unseen); |
+} |
+ |
+bool ReadingListModelImpl::LoadPersistentHasUnseen() { |
+ DCHECK_CURRENTLY_ON(web::WebThread::UI); |
+ if (!pref_service_) { |
+ return false; |
+ } |
+ return pref_service_->GetBoolean( |
+ reading_list::prefs::kReadingListHasUnseenEntries); |
} |