Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(388)

Unified Diff: ios/chrome/browser/reading_list/reading_list_model_impl.cc

Issue 2451843002: Add Store+Sync to reading list. (Closed)
Patch Set: rebase Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 2012052a080ecee238c77bdf0ecb7630fb92dee2..20163c6341cf4301da2abf9b60ed50ed4479e270 100644
--- a/ios/chrome/browser/reading_list/reading_list_model_impl.cc
+++ b/ios/chrome/browser/reading_list/reading_list_model_impl.cc
@@ -4,10 +4,15 @@
#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 "base/strings/string_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/chrome/browser/reading_list/reading_list_store.h"
+#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.
#include "url/gurl.h"
ReadingListModelImpl::ReadingListModelImpl()
@@ -16,80 +21,126 @@ ReadingListModelImpl::ReadingListModelImpl()
ReadingListModelImpl::ReadingListModelImpl(
std::unique_ptr<ReadingListModelStorage> storage,
PrefService* pref_service)
- : pref_service_(pref_service), has_unseen_(false) {
+ : pref_service_(pref_service),
+ has_unseen_(false),
+ loaded_(false),
+ weak_ptr_factory_(this) {
+ DCHECK(CalledOnValidThread());
if (storage) {
storage_layer_ = std::move(storage);
- read_ = storage_layer_->LoadPersistentReadList();
- unread_ = storage_layer_->LoadPersistentUnreadList();
- has_unseen_ = GetPersistentHasUnseen();
+ storage_layer_->SetReadingListModel(this, this);
+ } else {
+ loaded_ = true;
+ read_ = base::MakeUnique<ReadingListEntries>();
+ unread_ = base::MakeUnique<ReadingListEntries>();
}
- loaded_ = true;
+ has_unseen_ = GetPersistentHasUnseen();
}
ReadingListModelImpl::~ReadingListModelImpl() {}
+void ReadingListModelImpl::StoreLoaded(
+ std::unique_ptr<ReadingListEntries> unread,
+ std::unique_ptr<ReadingListEntries> read) {
+ DCHECK(CalledOnValidThread());
+ read_ = std::move(read);
+ unread_ = std::move(unread);
+ loaded_ = true;
+ SortEntries();
+ for (auto& observer : observers_)
+ observer.ReadingListModelLoaded(this);
+}
+
void ReadingListModelImpl::Shutdown() {
+ DCHECK(CalledOnValidThread());
for (auto& observer : observers_)
observer.ReadingListModelBeingDeleted(this);
loaded_ = false;
}
bool ReadingListModelImpl::loaded() const {
+ DCHECK(CalledOnValidThread());
return loaded_;
}
size_t ReadingListModelImpl::unread_size() const {
- DCHECK(loaded());
- return unread_.size();
+ DCHECK(CalledOnValidThread());
+ if (!loaded())
+ return 0;
+ return unread_->size();
}
size_t ReadingListModelImpl::read_size() const {
- DCHECK(loaded());
- return read_.size();
+ DCHECK(CalledOnValidThread());
+ if (!loaded())
+ return 0;
+ return read_->size();
}
bool ReadingListModelImpl::HasUnseenEntries() const {
- DCHECK(loaded());
+ DCHECK(CalledOnValidThread());
+ if (!loaded())
+ return false;
return unread_size() && has_unseen_;
}
void ReadingListModelImpl::ResetUnseenEntries() {
+ DCHECK(CalledOnValidThread());
DCHECK(loaded());
has_unseen_ = false;
- if (storage_layer_ && !IsPerformingBatchUpdates())
+ if (!IsPerformingBatchUpdates())
SetPersistentHasUnseen(false);
}
const ReadingListEntry& ReadingListModelImpl::GetUnreadEntryAtIndex(
size_t index) const {
+ DCHECK(CalledOnValidThread());
DCHECK(loaded());
- return unread_[index];
+ return unread_->at(index);
}
const ReadingListEntry& ReadingListModelImpl::GetReadEntryAtIndex(
size_t index) const {
+ DCHECK(CalledOnValidThread());
DCHECK(loaded());
- return read_[index];
+ return read_->at(index);
}
const ReadingListEntry* ReadingListModelImpl::GetEntryFromURL(
- const GURL& gurl) const {
+ const GURL& gurl,
+ bool* read) const {
+ DCHECK(CalledOnValidThread());
+ DCHECK(loaded());
+ return GetMutableEntryFromURL(gurl, read);
+}
+
+ReadingListEntry* ReadingListModelImpl::GetMutableEntryFromURL(
+ const GURL& gurl,
+ bool* read) const {
+ DCHECK(CalledOnValidThread());
DCHECK(loaded());
+ bool is_read;
ReadingListEntry entry(gurl, std::string());
- auto it = std::find(read_.begin(), read_.end(), entry);
- if (it == read_.end()) {
- it = std::find(unread_.begin(), unread_.end(), entry);
- if (it == unread_.end())
+ auto it = std::find(read_->begin(), read_->end(), entry);
+ is_read = true;
+ if (it == read_->end()) {
+ it = std::find(unread_->begin(), unread_->end(), entry);
+ is_read = false;
+ if (it == unread_->end())
return nullptr;
}
+ if (read) {
+ *read = is_read;
+ }
return &(*it);
}
bool ReadingListModelImpl::CallbackEntryURL(
const GURL& url,
base::Callback<void(const ReadingListEntry&)> callback) const {
+ DCHECK(CalledOnValidThread());
DCHECK(loaded());
- const ReadingListEntry* entry = GetEntryFromURL(url);
+ const ReadingListEntry* entry = GetMutableEntryFromURL(url, nullptr);
if (entry) {
callback.Run(*entry);
return true;
@@ -97,38 +148,117 @@ bool ReadingListModelImpl::CallbackEntryURL(
return false;
}
+void ReadingListModelImpl::SyncAddEntry(std::unique_ptr<ReadingListEntry> entry,
+ bool read) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(loaded());
+ bool is_existing_entry_read;
+ ReadingListEntry* existing_entry =
+ GetMutableEntryFromURL(entry->URL(), &is_existing_entry_read);
+ if (!existing_entry) {
+ if (storage_layer_) {
+ storage_layer_->SaveEntry(*entry, read, true);
+ }
+ if (read) {
+ for (auto& observer : observers_)
+ observer.ReadingListWillAddReadEntry(this, *entry);
+ read_->insert(read_->begin(), std::move(*entry));
+ } else {
+ for (auto& observer : observers_)
+ observer.ReadingListWillAddUnreadEntry(this, *entry);
+ has_unseen_ = true;
+ SetPersistentHasUnseen(true);
+ unread_->insert(unread_->begin(), std::move(*entry));
+ }
+ for (auto& observer : observers_)
+ observer.ReadingListDidApplyChanges(this);
+ return;
+ }
+
+ if (existing_entry->UpdateTime() > entry->UpdateTime()) {
+ // Existing entry is newer than the sync one. Do not update it.
+ return;
+ }
+
+ // Merge local data in new entry.
+ entry->MergeLocalStateFrom(*existing_entry);
+
+ 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.
+ auto result = std::find(read_->begin(), read_->end(), *existing_entry);
+ DCHECK(result != read_->end());
+ int index = std::distance(read_->begin(), result);
+ for (auto& observer : observers_)
+ observer.ReadingListWillMoveEntry(this, index, true);
+
+ 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
+ } else {
+ auto result = std::find(unread_->begin(), unread_->end(), *existing_entry);
+ DCHECK(result != unread_->end());
+ int index = std::distance(unread_->begin(), result);
+ for (auto& observer : observers_)
+ observer.ReadingListWillMoveEntry(this, index, false);
+
+ unread_->erase(result);
+ }
+
+ if (storage_layer_) {
pavely 2016/11/14 07:45:33 SyncAddEntry should be invoked from ReadingListSto
Olivier 2016/11/14 11:36:49 Done.
+ storage_layer_->SaveEntry(*entry, read, true);
+ }
+
+ if (read) {
+ read_->push_back(std::move(*entry));
+ } else {
+ unread_->push_back(std::move(*entry));
+ }
+ for (auto& observer : observers_)
+ observer.ReadingListDidApplyChanges(this);
+}
+
+void ReadingListModelImpl::SyncRemoveEntry(const GURL& gurl) {
+ RemoveEntryByURLImpl(gurl, true);
+}
+
// Temporary method
void ReadingListModelImpl::RemoveEntryByUrl(const GURL& url) {
return RemoveEntryByURL(url);
}
void ReadingListModelImpl::RemoveEntryByURL(const GURL& url) {
+ RemoveEntryByURLImpl(url, false);
+}
+
+void ReadingListModelImpl::RemoveEntryByURLImpl(const GURL& url,
+ bool from_sync) {
+ DCHECK(CalledOnValidThread());
DCHECK(loaded());
const ReadingListEntry entry(url, std::string());
- auto result = std::find(unread_.begin(), unread_.end(), entry);
- if (result != unread_.end()) {
- for (auto& observer : observers_) {
+ auto result = std::find(unread_->begin(), unread_->end(), entry);
+ if (result != unread_->end()) {
+ for (auto& observer : observers_)
observer.ReadingListWillRemoveUnreadEntry(
- this, std::distance(unread_.begin(), result));
+ this, std::distance(unread_->begin(), result));
+
+ if (storage_layer_) {
+ storage_layer_->RemoveEntry(*result, from_sync);
}
- unread_.erase(result);
- if (storage_layer_ && !IsPerformingBatchUpdates())
- storage_layer_->SavePersistentUnreadList(unread_);
+ unread_->erase(result);
+
for (auto& observer : observers_)
observer.ReadingListDidApplyChanges(this);
return;
}
- result = std::find(read_.begin(), read_.end(), entry);
- if (result != read_.end()) {
- for (auto& observer : observers_) {
+ result = std::find(read_->begin(), read_->end(), entry);
+ if (result != read_->end()) {
+ for (auto& observer : observers_)
observer.ReadingListWillRemoveReadEntry(
- this, std::distance(read_.begin(), result));
+ this, std::distance(read_->begin(), result));
+ if (storage_layer_) {
+ storage_layer_->RemoveEntry(*result, from_sync);
}
- read_.erase(result);
- if (storage_layer_ && !IsPerformingBatchUpdates())
- storage_layer_->SavePersistentReadList(read_);
+ read_->erase(result);
+
for (auto& observer : observers_)
observer.ReadingListDidApplyChanges(this);
return;
@@ -138,6 +268,7 @@ void ReadingListModelImpl::RemoveEntryByURL(const GURL& url) {
const ReadingListEntry& ReadingListModelImpl::AddEntry(
const GURL& url,
const std::string& title) {
+ DCHECK(CalledOnValidThread());
DCHECK(loaded());
RemoveEntryByURL(url);
@@ -147,92 +278,98 @@ const ReadingListEntry& ReadingListModelImpl::AddEntry(
ReadingListEntry entry(url, trimmedTitle);
for (auto& observer : observers_)
observer.ReadingListWillAddUnreadEntry(this, entry);
- unread_.insert(unread_.begin(), std::move(entry));
has_unseen_ = true;
- if (storage_layer_ && !IsPerformingBatchUpdates()) {
- storage_layer_->SavePersistentUnreadList(unread_);
- SetPersistentHasUnseen(true);
+ SetPersistentHasUnseen(true);
+ if (storage_layer_) {
+ storage_layer_->SaveEntry(entry, false, false);
}
+ unread_->insert(unread_->begin(), std::move(entry));
+
for (auto& observer : observers_)
observer.ReadingListDidApplyChanges(this);
- return *unread_.begin();
+ return *unread_->begin();
}
void ReadingListModelImpl::MarkUnreadByURL(const GURL& url) {
+ DCHECK(CalledOnValidThread());
DCHECK(loaded());
ReadingListEntry entry(url, std::string());
- auto result = std::find(read_.begin(), read_.end(), entry);
- if (result == read_.end())
+ auto result = std::find(read_->begin(), read_->end(), entry);
+ if (result == read_->end())
return;
for (ReadingListModelObserver& observer : observers_) {
- observer.ReadingListWillMoveEntry(this,
- std::distance(read_.begin(), result));
+ observer.ReadingListWillMoveEntry(
+ this, std::distance(read_->begin(), result), true);
}
- unread_.insert(unread_.begin(), std::move(*result));
- read_.erase(result);
-
- if (storage_layer_ && !IsPerformingBatchUpdates()) {
- storage_layer_->SavePersistentUnreadList(read_);
- storage_layer_->SavePersistentReadList(unread_);
+ result->MarkEntryUpdated();
+ if (storage_layer_) {
+ storage_layer_->SaveEntry(*result, false, false);
}
+
+ unread_->insert(unread_->begin(), std::move(*result));
+ read_->erase(result);
+
for (ReadingListModelObserver& observer : observers_) {
observer.ReadingListDidApplyChanges(this);
}
}
void ReadingListModelImpl::MarkReadByURL(const GURL& url) {
+ DCHECK(CalledOnValidThread());
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 (auto& observer : observers_) {
- observer.ReadingListWillMoveEntry(this,
- std::distance(unread_.begin(), result));
+ for (auto& observer : observers_)
+ observer.ReadingListWillMoveEntry(
+ this, std::distance(unread_->begin(), result), false);
+
+ result->MarkEntryUpdated();
+ if (storage_layer_) {
+ storage_layer_->SaveEntry(*result, true, false);
}
- read_.insert(read_.begin(), std::move(*result));
- unread_.erase(result);
+ read_->insert(read_->begin(), std::move(*result));
+ unread_->erase(result);
- if (storage_layer_ && !IsPerformingBatchUpdates()) {
- storage_layer_->SavePersistentUnreadList(unread_);
- storage_layer_->SavePersistentReadList(read_);
- }
for (auto& observer : observers_)
observer.ReadingListDidApplyChanges(this);
}
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
const std::string& title) {
+ DCHECK(CalledOnValidThread());
DCHECK(loaded());
const ReadingListEntry entry(url, std::string());
- auto result = std::find(unread_.begin(), unread_.end(), entry);
- if (result != unread_.end()) {
- for (auto& observer : observers_) {
+ auto result = std::find(unread_->begin(), unread_->end(), entry);
+ if (result != unread_->end()) {
+ for (auto& observer : observers_)
observer.ReadingListWillUpdateUnreadEntry(
- this, std::distance(unread_.begin(), result));
- }
+ this, std::distance(unread_->begin(), result));
result->SetTitle(title);
- if (storage_layer_ && !IsPerformingBatchUpdates())
- storage_layer_->SavePersistentUnreadList(unread_);
+
+ if (storage_layer_) {
+ storage_layer_->SaveEntry(*result, false, false);
+ }
for (auto& observer : observers_)
observer.ReadingListDidApplyChanges(this);
return;
}
- result = std::find(read_.begin(), read_.end(), entry);
- if (result != read_.end()) {
- for (auto& observer : observers_) {
+ result = std::find(read_->begin(), read_->end(), entry);
+ if (result != read_->end()) {
+ for (auto& observer : observers_)
observer.ReadingListWillUpdateReadEntry(
- this, std::distance(read_.begin(), result));
- }
+ this, std::distance(read_->begin(), result));
result->SetTitle(title);
- if (storage_layer_ && !IsPerformingBatchUpdates())
- storage_layer_->SavePersistentReadList(read_);
+ if (storage_layer_) {
+ storage_layer_->SaveEntry(*result, true, false);
+ }
for (auto& observer : observers_)
observer.ReadingListDidApplyChanges(this);
return;
@@ -241,32 +378,33 @@ void ReadingListModelImpl::SetEntryTitle(const GURL& url,
void ReadingListModelImpl::SetEntryDistilledURL(const GURL& url,
const GURL& distilled_url) {
+ DCHECK(CalledOnValidThread());
DCHECK(loaded());
const ReadingListEntry entry(url, std::string());
- auto result = std::find(unread_.begin(), unread_.end(), entry);
- if (result != unread_.end()) {
- for (auto& observer : observers_) {
+ auto result = std::find(unread_->begin(), unread_->end(), entry);
+ if (result != unread_->end()) {
+ for (auto& observer : observers_)
observer.ReadingListWillUpdateUnreadEntry(
- this, std::distance(unread_.begin(), result));
- }
+ this, std::distance(unread_->begin(), result));
result->SetDistilledURL(distilled_url);
- if (storage_layer_ && !IsPerformingBatchUpdates())
- storage_layer_->SavePersistentUnreadList(unread_);
+ if (storage_layer_) {
+ storage_layer_->SaveEntry(*result, false, false);
+ }
for (auto& observer : observers_)
observer.ReadingListDidApplyChanges(this);
return;
}
- result = std::find(read_.begin(), read_.end(), entry);
- if (result != read_.end()) {
- for (auto& observer : observers_) {
+ result = std::find(read_->begin(), read_->end(), entry);
+ if (result != read_->end()) {
+ for (auto& observer : observers_)
observer.ReadingListWillUpdateReadEntry(
- this, std::distance(read_.begin(), result));
- }
+ this, std::distance(read_->begin(), result));
result->SetDistilledURL(distilled_url);
- if (storage_layer_ && !IsPerformingBatchUpdates())
- storage_layer_->SavePersistentReadList(read_);
+ if (storage_layer_) {
+ storage_layer_->SaveEntry(*result, true, false);
+ }
for (auto& observer : observers_)
observer.ReadingListDidApplyChanges(this);
return;
@@ -276,49 +414,75 @@ void ReadingListModelImpl::SetEntryDistilledURL(const GURL& url,
void ReadingListModelImpl::SetEntryDistilledState(
const GURL& url,
ReadingListEntry::DistillationState state) {
+ DCHECK(CalledOnValidThread());
DCHECK(loaded());
const ReadingListEntry entry(url, std::string());
- auto result = std::find(unread_.begin(), unread_.end(), entry);
- if (result != unread_.end()) {
- for (auto& observer : observers_) {
+ auto result = std::find(unread_->begin(), unread_->end(), entry);
+ if (result != unread_->end()) {
+ for (auto& observer : observers_)
observer.ReadingListWillUpdateUnreadEntry(
- this, std::distance(unread_.begin(), result));
- }
+ this, std::distance(unread_->begin(), result));
result->SetDistilledState(state);
- if (storage_layer_ && !IsPerformingBatchUpdates())
- storage_layer_->SavePersistentUnreadList(unread_);
+ if (storage_layer_) {
+ storage_layer_->SaveEntry(*result, false, false);
+ }
for (auto& observer : observers_)
observer.ReadingListDidApplyChanges(this);
return;
}
- result = std::find(read_.begin(), read_.end(), entry);
- if (result != read_.end()) {
- for (auto& observer : observers_) {
+ result = std::find(read_->begin(), read_->end(), entry);
+ if (result != read_->end()) {
+ for (auto& observer : observers_)
observer.ReadingListWillUpdateReadEntry(
- this, std::distance(read_.begin(), result));
- }
+ this, std::distance(read_->begin(), result));
result->SetDistilledState(state);
- if (storage_layer_ && !IsPerformingBatchUpdates())
- storage_layer_->SavePersistentReadList(read_);
+ if (storage_layer_) {
+ storage_layer_->SaveEntry(*result, true, false);
+ }
for (auto& observer : observers_)
observer.ReadingListDidApplyChanges(this);
return;
}
};
-void ReadingListModelImpl::EndBatchUpdates() {
- ReadingListModel::EndBatchUpdates();
- if (IsPerformingBatchUpdates() || !storage_layer_) {
- return;
+std::unique_ptr<ReadingListModel::ScopedReadingListBatchUpdate>
+ReadingListModelImpl::CreateBatchToken() {
+ return base::MakeUnique<ReadingListModelImpl::ScopedReadingListBatchUpdate>(
+ this);
+}
+
+ReadingListModelImpl::ScopedReadingListBatchUpdate::
+ ScopedReadingListBatchUpdate(ReadingListModelImpl* model)
+ : ReadingListModel::ScopedReadingListBatchUpdate::
+ ScopedReadingListBatchUpdate(model) {
+ if (model->StorageLayer()) {
+ storage_token_ = model->StorageLayer()->EnsureBatchCreated();
+ }
+}
+
+ReadingListModelImpl::ScopedReadingListBatchUpdate::
+ ~ScopedReadingListBatchUpdate() {
+ storage_token_.reset();
+}
+
+void ReadingListModelImpl::LeavingBatchUpdates() {
+ DCHECK(CalledOnValidThread());
+ if (storage_layer_) {
+ SetPersistentHasUnseen(has_unseen_);
+ SortEntries();
}
- storage_layer_->SavePersistentUnreadList(unread_);
- storage_layer_->SavePersistentReadList(read_);
- SetPersistentHasUnseen(has_unseen_);
+ ReadingListModel::LeavingBatchUpdates();
+}
+
+void ReadingListModelImpl::EnteringBatchUpdates() {
+ DCHECK(CalledOnValidThread());
+ ReadingListModel::EnteringBatchUpdates();
}
void ReadingListModelImpl::SetPersistentHasUnseen(bool has_unseen) {
+ DCHECK(CalledOnValidThread());
if (!pref_service_) {
return;
}
@@ -327,9 +491,30 @@ void ReadingListModelImpl::SetPersistentHasUnseen(bool has_unseen) {
}
bool ReadingListModelImpl::GetPersistentHasUnseen() {
+ DCHECK(CalledOnValidThread());
if (!pref_service_) {
return false;
}
return pref_service_->GetBoolean(
reading_list::prefs::kReadingListHasUnseenEntries);
}
+
+syncer::ModelTypeSyncBridge* ReadingListModelImpl::GetModelTypeSyncBridge() {
+ DCHECK(loaded());
+ if (!storage_layer_)
+ return nullptr;
+ return storage_layer_->GetModelTypeSyncBridge();
+}
+
+void ReadingListModelImpl::SortEntries() {
+ DCHECK(CalledOnValidThread());
+ DCHECK(loaded());
+ std::sort(read_->begin(), read_->end(),
+ ReadingListEntry::CompareEntryUpdateTime);
+ std::sort(unread_->begin(), unread_->end(),
+ ReadingListEntry::CompareEntryUpdateTime);
+}
+
+ReadingListModelStorage* ReadingListModelImpl::StorageLayer() {
+ return storage_layer_.get();
+}

Powered by Google App Engine
This is Rietveld 408576698