| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "components/dom_distiller/core/dom_distiller_store.h" | 5 #include "components/dom_distiller/core/dom_distiller_store.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "components/dom_distiller/core/article_entry.h" | 9 #include "components/dom_distiller/core/article_entry.h" |
| 10 #include "sync/api/sync_change.h" | 10 #include "sync/api/sync_change.h" |
| 11 #include "sync/protocol/article_specifics.pb.h" | 11 #include "sync/protocol/article_specifics.pb.h" |
| 12 #include "sync/protocol/sync.pb.h" | 12 #include "sync/protocol/sync.pb.h" |
| 13 | 13 |
| 14 using leveldb_proto::ProtoDatabase; |
| 14 using sync_pb::ArticleSpecifics; | 15 using sync_pb::ArticleSpecifics; |
| 15 using sync_pb::EntitySpecifics; | 16 using sync_pb::EntitySpecifics; |
| 16 using syncer::ModelType; | 17 using syncer::ModelType; |
| 17 using syncer::SyncChange; | 18 using syncer::SyncChange; |
| 18 using syncer::SyncChangeList; | 19 using syncer::SyncChangeList; |
| 19 using syncer::SyncData; | 20 using syncer::SyncData; |
| 20 using syncer::SyncDataList; | 21 using syncer::SyncDataList; |
| 21 using syncer::SyncError; | 22 using syncer::SyncError; |
| 22 using syncer::SyncMergeResult; | 23 using syncer::SyncMergeResult; |
| 23 | 24 |
| 24 namespace dom_distiller { | 25 namespace dom_distiller { |
| 25 | 26 |
| 26 DomDistillerStore::DomDistillerStore( | 27 DomDistillerStore::DomDistillerStore( |
| 27 scoped_ptr<DomDistillerDatabaseInterface> database, | 28 scoped_ptr<ProtoDatabase<ArticleEntry> > database, |
| 28 const base::FilePath& database_dir) | 29 const base::FilePath& database_dir) |
| 29 : database_(database.Pass()), | 30 : database_(database.Pass()), |
| 30 database_loaded_(false), | 31 database_loaded_(false), |
| 31 weak_ptr_factory_(this) { | 32 weak_ptr_factory_(this) { |
| 32 database_->Init(database_dir, | 33 database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit, |
| 33 base::Bind(&DomDistillerStore::OnDatabaseInit, | 34 weak_ptr_factory_.GetWeakPtr())); |
| 34 weak_ptr_factory_.GetWeakPtr())); | |
| 35 } | 35 } |
| 36 | 36 |
| 37 DomDistillerStore::DomDistillerStore( | 37 DomDistillerStore::DomDistillerStore( |
| 38 scoped_ptr<DomDistillerDatabaseInterface> database, | 38 scoped_ptr<ProtoDatabase<ArticleEntry> > database, |
| 39 const std::vector<ArticleEntry>& initial_data, | 39 const std::vector<ArticleEntry>& initial_data, |
| 40 const base::FilePath& database_dir) | 40 const base::FilePath& database_dir) |
| 41 : database_(database.Pass()), | 41 : database_(database.Pass()), |
| 42 database_loaded_(false), | 42 database_loaded_(false), |
| 43 model_(initial_data), | 43 model_(initial_data), |
| 44 weak_ptr_factory_(this) { | 44 weak_ptr_factory_(this) { |
| 45 database_->Init(database_dir, | 45 database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit, |
| 46 base::Bind(&DomDistillerStore::OnDatabaseInit, | 46 weak_ptr_factory_.GetWeakPtr())); |
| 47 weak_ptr_factory_.GetWeakPtr())); | |
| 48 } | 47 } |
| 49 | 48 |
| 50 DomDistillerStore::~DomDistillerStore() {} | 49 DomDistillerStore::~DomDistillerStore() {} |
| 51 | 50 |
| 52 // DomDistillerStoreInterface implementation. | 51 // DomDistillerStoreInterface implementation. |
| 53 syncer::SyncableService* DomDistillerStore::GetSyncableService() { | 52 syncer::SyncableService* DomDistillerStore::GetSyncableService() { |
| 54 return this; | 53 return this; |
| 55 } | 54 } |
| 56 | 55 |
| 57 bool DomDistillerStore::GetEntryById(const std::string& entry_id, | 56 bool DomDistillerStore::GetEntryById(const std::string& entry_id, |
| 58 ArticleEntry* entry) { | 57 ArticleEntry* entry) { |
| 59 return model_.GetEntryById(entry_id, entry); | 58 return model_.GetEntryById(entry_id, entry); |
| 60 } | 59 } |
| 61 | 60 |
| 62 bool DomDistillerStore::GetEntryByUrl(const GURL& url, | 61 bool DomDistillerStore::GetEntryByUrl(const GURL& url, ArticleEntry* entry) { |
| 63 ArticleEntry* entry) { | |
| 64 return model_.GetEntryByUrl(url, entry); | 62 return model_.GetEntryByUrl(url, entry); |
| 65 } | 63 } |
| 66 | 64 |
| 67 | |
| 68 bool DomDistillerStore::AddEntry(const ArticleEntry& entry) { | 65 bool DomDistillerStore::AddEntry(const ArticleEntry& entry) { |
| 69 if (!database_loaded_) { | 66 if (!database_loaded_) { |
| 70 return false; | 67 return false; |
| 71 } | 68 } |
| 72 | 69 |
| 73 if (model_.GetEntryById(entry.entry_id(), NULL)) { | 70 if (model_.GetEntryById(entry.entry_id(), NULL)) { |
| 74 DVLOG(1) << "Already have entry with id " << entry.entry_id() << "."; | 71 DVLOG(1) << "Already have entry with id " << entry.entry_id() << "."; |
| 75 return false; | 72 return false; |
| 76 } | 73 } |
| 77 | 74 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 void DomDistillerStore::RemoveObserver(DomDistillerObserver* observer) { | 155 void DomDistillerStore::RemoveObserver(DomDistillerObserver* observer) { |
| 159 observers_.RemoveObserver(observer); | 156 observers_.RemoveObserver(observer); |
| 160 } | 157 } |
| 161 | 158 |
| 162 std::vector<ArticleEntry> DomDistillerStore::GetEntries() const { | 159 std::vector<ArticleEntry> DomDistillerStore::GetEntries() const { |
| 163 return model_.GetEntries(); | 160 return model_.GetEntries(); |
| 164 } | 161 } |
| 165 | 162 |
| 166 // syncer::SyncableService implementation. | 163 // syncer::SyncableService implementation. |
| 167 SyncMergeResult DomDistillerStore::MergeDataAndStartSyncing( | 164 SyncMergeResult DomDistillerStore::MergeDataAndStartSyncing( |
| 168 ModelType type, | 165 ModelType type, const SyncDataList& initial_sync_data, |
| 169 const SyncDataList& initial_sync_data, | |
| 170 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, | 166 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, |
| 171 scoped_ptr<syncer::SyncErrorFactory> error_handler) { | 167 scoped_ptr<syncer::SyncErrorFactory> error_handler) { |
| 172 DCHECK_EQ(syncer::ARTICLES, type); | 168 DCHECK_EQ(syncer::ARTICLES, type); |
| 173 DCHECK(!sync_processor_); | 169 DCHECK(!sync_processor_); |
| 174 DCHECK(!error_factory_); | 170 DCHECK(!error_factory_); |
| 175 sync_processor_.reset(sync_processor.release()); | 171 sync_processor_.reset(sync_processor.release()); |
| 176 error_factory_.reset(error_handler.release()); | 172 error_factory_.reset(error_handler.release()); |
| 177 | 173 |
| 178 SyncChangeList database_changes; | 174 SyncChangeList database_changes; |
| 179 SyncChangeList sync_changes; | 175 SyncChangeList sync_changes; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 203 ApplyChangesToModel(change_list, &database_changes, &sync_changes); | 199 ApplyChangesToModel(change_list, &database_changes, &sync_changes); |
| 204 ApplyChangesToDatabase(database_changes); | 200 ApplyChangesToDatabase(database_changes); |
| 205 DCHECK_EQ(size_t(0), sync_changes.size()); | 201 DCHECK_EQ(size_t(0), sync_changes.size()); |
| 206 return SyncError(); | 202 return SyncError(); |
| 207 } | 203 } |
| 208 | 204 |
| 209 void DomDistillerStore::NotifyObservers(const syncer::SyncChangeList& changes) { | 205 void DomDistillerStore::NotifyObservers(const syncer::SyncChangeList& changes) { |
| 210 if (observers_.might_have_observers() && changes.size() > 0) { | 206 if (observers_.might_have_observers() && changes.size() > 0) { |
| 211 std::vector<DomDistillerObserver::ArticleUpdate> article_changes; | 207 std::vector<DomDistillerObserver::ArticleUpdate> article_changes; |
| 212 for (SyncChangeList::const_iterator it = changes.begin(); | 208 for (SyncChangeList::const_iterator it = changes.begin(); |
| 213 it != changes.end(); | 209 it != changes.end(); ++it) { |
| 214 ++it) { | |
| 215 DomDistillerObserver::ArticleUpdate article_update; | 210 DomDistillerObserver::ArticleUpdate article_update; |
| 216 switch (it->change_type()) { | 211 switch (it->change_type()) { |
| 217 case SyncChange::ACTION_ADD: | 212 case SyncChange::ACTION_ADD: |
| 218 article_update.update_type = DomDistillerObserver::ArticleUpdate::ADD; | 213 article_update.update_type = DomDistillerObserver::ArticleUpdate::ADD; |
| 219 break; | 214 break; |
| 220 case SyncChange::ACTION_UPDATE: | 215 case SyncChange::ACTION_UPDATE: |
| 221 article_update.update_type = | 216 article_update.update_type = |
| 222 DomDistillerObserver::ArticleUpdate::UPDATE; | 217 DomDistillerObserver::ArticleUpdate::UPDATE; |
| 223 break; | 218 break; |
| 224 case SyncChange::ACTION_DELETE: | 219 case SyncChange::ACTION_DELETE: |
| 225 article_update.update_type = | 220 article_update.update_type = |
| 226 DomDistillerObserver::ArticleUpdate::REMOVE; | 221 DomDistillerObserver::ArticleUpdate::REMOVE; |
| 227 break; | 222 break; |
| 228 case SyncChange::ACTION_INVALID: | 223 case SyncChange::ACTION_INVALID: |
| 229 NOTREACHED(); | 224 NOTREACHED(); |
| 230 break; | 225 break; |
| 231 } | 226 } |
| 232 const ArticleEntry& entry = GetEntryFromChange(*it); | 227 const ArticleEntry& entry = GetEntryFromChange(*it); |
| 233 article_update.entry_id = entry.entry_id(); | 228 article_update.entry_id = entry.entry_id(); |
| 234 article_changes.push_back(article_update); | 229 article_changes.push_back(article_update); |
| 235 } | 230 } |
| 236 FOR_EACH_OBSERVER(DomDistillerObserver, | 231 FOR_EACH_OBSERVER(DomDistillerObserver, observers_, |
| 237 observers_, | |
| 238 ArticleEntriesUpdated(article_changes)); | 232 ArticleEntriesUpdated(article_changes)); |
| 239 } | 233 } |
| 240 } | 234 } |
| 241 | 235 |
| 242 void DomDistillerStore::ApplyChangesToModel( | 236 void DomDistillerStore::ApplyChangesToModel(const SyncChangeList& changes, |
| 243 const SyncChangeList& changes, | 237 SyncChangeList* changes_applied, |
| 244 SyncChangeList* changes_applied, | 238 SyncChangeList* changes_missing) { |
| 245 SyncChangeList* changes_missing) { | |
| 246 model_.ApplyChangesToModel(changes, changes_applied, changes_missing); | 239 model_.ApplyChangesToModel(changes, changes_applied, changes_missing); |
| 247 NotifyObservers(*changes_applied); | 240 NotifyObservers(*changes_applied); |
| 248 } | 241 } |
| 249 | 242 |
| 250 void DomDistillerStore::OnDatabaseInit(bool success) { | 243 void DomDistillerStore::OnDatabaseInit(bool success) { |
| 251 if (!success) { | 244 if (!success) { |
| 252 DVLOG(1) << "DOM Distiller database init failed."; | 245 DVLOG(1) << "DOM Distiller database init failed."; |
| 253 database_.reset(); | 246 database_.reset(); |
| 254 return; | 247 return; |
| 255 } | 248 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 } | 299 } |
| 307 | 300 |
| 308 bool DomDistillerStore::ApplyChangesToDatabase( | 301 bool DomDistillerStore::ApplyChangesToDatabase( |
| 309 const SyncChangeList& change_list) { | 302 const SyncChangeList& change_list) { |
| 310 if (!database_loaded_) { | 303 if (!database_loaded_) { |
| 311 return false; | 304 return false; |
| 312 } | 305 } |
| 313 if (change_list.empty()) { | 306 if (change_list.empty()) { |
| 314 return true; | 307 return true; |
| 315 } | 308 } |
| 316 scoped_ptr<EntryVector> entries_to_save(new EntryVector()); | 309 scoped_ptr<ProtoDatabase<ArticleEntry>::KeyEntryVector> entries_to_save( |
| 317 scoped_ptr<EntryVector> entries_to_remove(new EntryVector()); | 310 new ProtoDatabase<ArticleEntry>::KeyEntryVector()); |
| 311 scoped_ptr<std::vector<std::string> > keys_to_remove( |
| 312 new std::vector<std::string>()); |
| 318 | 313 |
| 319 for (SyncChangeList::const_iterator it = change_list.begin(); | 314 for (SyncChangeList::const_iterator it = change_list.begin(); |
| 320 it != change_list.end(); | 315 it != change_list.end(); ++it) { |
| 321 ++it) { | 316 if (it->change_type() == SyncChange::ACTION_DELETE) { |
| 322 if (it->change_type() == SyncChange::ACTION_DELETE) | 317 ArticleEntry entry = GetEntryFromChange(*it); |
| 323 entries_to_remove->push_back(GetEntryFromChange(*it)); | 318 keys_to_remove->push_back(entry.entry_id()); |
| 324 else | 319 } else { |
| 325 entries_to_save->push_back(GetEntryFromChange(*it)); | 320 ArticleEntry entry = GetEntryFromChange(*it); |
| 321 entries_to_save->push_back(std::make_pair(entry.entry_id(), entry)); |
| 322 } |
| 326 } | 323 } |
| 327 database_->UpdateEntries(entries_to_save.Pass(), | 324 database_->UpdateEntries(entries_to_save.Pass(), keys_to_remove.Pass(), |
| 328 entries_to_remove.Pass(), | |
| 329 base::Bind(&DomDistillerStore::OnDatabaseSave, | 325 base::Bind(&DomDistillerStore::OnDatabaseSave, |
| 330 weak_ptr_factory_.GetWeakPtr())); | 326 weak_ptr_factory_.GetWeakPtr())); |
| 331 return true; | 327 return true; |
| 332 } | 328 } |
| 333 | 329 |
| 334 SyncMergeResult DomDistillerStore::MergeDataWithModel( | 330 SyncMergeResult DomDistillerStore::MergeDataWithModel( |
| 335 const SyncDataList& data, | 331 const SyncDataList& data, SyncChangeList* changes_applied, |
| 336 SyncChangeList* changes_applied, | |
| 337 SyncChangeList* changes_missing) { | 332 SyncChangeList* changes_missing) { |
| 338 DCHECK(changes_applied); | 333 DCHECK(changes_applied); |
| 339 DCHECK(changes_missing); | 334 DCHECK(changes_missing); |
| 340 | 335 |
| 341 SyncMergeResult result(syncer::ARTICLES); | 336 SyncMergeResult result(syncer::ARTICLES); |
| 342 result.set_num_items_before_association(model_.GetNumEntries()); | 337 result.set_num_items_before_association(model_.GetNumEntries()); |
| 343 | 338 |
| 344 SyncChangeList changes_to_apply; | 339 SyncChangeList changes_to_apply; |
| 345 model_.CalculateChangesForMerge(data, &changes_to_apply, changes_missing); | 340 model_.CalculateChangesForMerge(data, &changes_to_apply, changes_missing); |
| 346 SyncError error; | 341 SyncError error; |
| 347 ApplyChangesToModel(changes_to_apply, changes_applied, changes_missing); | 342 ApplyChangesToModel(changes_to_apply, changes_applied, changes_missing); |
| 348 | 343 |
| 349 int num_added = 0; | 344 int num_added = 0; |
| 350 int num_modified = 0; | 345 int num_modified = 0; |
| 351 for (SyncChangeList::const_iterator it = changes_applied->begin(); | 346 for (SyncChangeList::const_iterator it = changes_applied->begin(); |
| 352 it != changes_applied->end(); | 347 it != changes_applied->end(); ++it) { |
| 353 ++it) { | |
| 354 DCHECK(it->IsValid()); | 348 DCHECK(it->IsValid()); |
| 355 switch (it->change_type()) { | 349 switch (it->change_type()) { |
| 356 case SyncChange::ACTION_ADD: | 350 case SyncChange::ACTION_ADD: |
| 357 num_added++; | 351 num_added++; |
| 358 break; | 352 break; |
| 359 case SyncChange::ACTION_UPDATE: | 353 case SyncChange::ACTION_UPDATE: |
| 360 num_modified++; | 354 num_modified++; |
| 361 break; | 355 break; |
| 362 default: | 356 default: |
| 363 NOTREACHED(); | 357 NOTREACHED(); |
| 364 } | 358 } |
| 365 } | 359 } |
| 366 result.set_num_items_added(num_added); | 360 result.set_num_items_added(num_added); |
| 367 result.set_num_items_modified(num_modified); | 361 result.set_num_items_modified(num_modified); |
| 368 result.set_num_items_deleted(0); | 362 result.set_num_items_deleted(0); |
| 369 | 363 |
| 370 result.set_pre_association_version(0); | 364 result.set_pre_association_version(0); |
| 371 result.set_num_items_after_association(model_.GetNumEntries()); | 365 result.set_num_items_after_association(model_.GetNumEntries()); |
| 372 result.set_error(error); | 366 result.set_error(error); |
| 373 | 367 |
| 374 return result; | 368 return result; |
| 375 } | 369 } |
| 376 | 370 |
| 377 } // namespace dom_distiller | 371 } // namespace dom_distiller |
| OLD | NEW |