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 |