14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "components/dom_distiller/core/dom_distiller_store.h"
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/bind.h"
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/logging.h"
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "components/dom_distiller/core/article_entry.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sync/api/sync_change.h"
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sync/protocol/article_specifics.pb.h"
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sync/protocol/sync.pb.h"
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using leveldb_proto::ProtoDatabase;
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using sync_pb::ArticleSpecifics;
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using sync_pb::EntitySpecifics;
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using syncer::ModelType;
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using syncer::SyncChange;
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using syncer::SyncChangeList;
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using syncer::SyncData;
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using syncer::SyncDataList;
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using syncer::SyncError;
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using syncer::SyncMergeResult;
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace dom_distiller {
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DomDistillerStore::DomDistillerStore(
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<ProtoDatabase<ArticleEntry> > database,
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const base::FilePath& database_dir)
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : database_(database.Pass()),
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      database_loaded_(false),
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_ptr_factory_(this) {
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit,
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           weak_ptr_factory_.GetWeakPtr()));
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DomDistillerStore::DomDistillerStore(
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<ProtoDatabase<ArticleEntry> > database,
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const std::vector<ArticleEntry>& initial_data,
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const base::FilePath& database_dir)
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : database_(database.Pass()),
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      database_loaded_(false),
431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      model_(initial_data),
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_ptr_factory_(this) {
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit,
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           weak_ptr_factory_.GetWeakPtr()));
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DomDistillerStore::~DomDistillerStore() {}
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// DomDistillerStoreInterface implementation.
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)syncer::SyncableService* DomDistillerStore::GetSyncableService() {
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return this;
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool DomDistillerStore::GetEntryById(const std::string& entry_id,
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                     ArticleEntry* entry) {
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return model_.GetEntryById(entry_id, entry);
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool DomDistillerStore::GetEntryByUrl(const GURL& url, ArticleEntry* entry) {
621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return model_.GetEntryByUrl(url, entry);
631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool DomDistillerStore::AddEntry(const ArticleEntry& entry) {
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!database_loaded_) {
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (model_.GetEntryById(entry.entry_id(), NULL)) {
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "Already have entry with id " << entry.entry_id() << ".";
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncChangeList changes_to_apply;
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  changes_to_apply.push_back(
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      SyncChange(FROM_HERE, SyncChange::ACTION_ADD, CreateLocalData(entry)));
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncChangeList changes_applied;
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncChangeList changes_missing;
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ApplyChangesToModel(changes_to_apply, &changes_applied, &changes_missing);
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK_EQ(size_t(0), changes_missing.size());
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK_EQ(size_t(1), changes_applied.size());
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ApplyChangesToSync(FROM_HERE, changes_applied);
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ApplyChangesToDatabase(changes_applied);
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return true;
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool DomDistillerStore::UpdateEntry(const ArticleEntry& entry) {
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!database_loaded_) {
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!model_.GetEntryById(entry.entry_id(), NULL)) {
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DVLOG(1) << "No entry with id " << entry.entry_id() << " found.";
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SyncChangeList changes_to_apply;
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  changes_to_apply.push_back(
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SyncChange(FROM_HERE, SyncChange::ACTION_UPDATE, CreateLocalData(entry)));
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SyncChangeList changes_applied;
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SyncChangeList changes_missing;
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ApplyChangesToModel(changes_to_apply, &changes_applied, &changes_missing);
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (changes_applied.size() != 1) {
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DVLOG(1) << "Failed to update entry with id " << entry.entry_id() << ".";
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ApplyChangesToSync(FROM_HERE, changes_applied);
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ApplyChangesToDatabase(changes_applied);
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool DomDistillerStore::RemoveEntry(const ArticleEntry& entry) {
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!database_loaded_) {
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!model_.GetEntryById(entry.entry_id(), NULL)) {
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "No entry with id " << entry.entry_id() << " found.";
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SyncChangeList changes_to_apply;
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  changes_to_apply.push_back(
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, CreateLocalData(entry)));
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SyncChangeList changes_applied;
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SyncChangeList changes_missing;
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ApplyChangesToModel(changes_to_apply, &changes_applied, &changes_missing);
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_EQ(size_t(0), changes_missing.size());
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_EQ(size_t(1), changes_applied.size());
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ApplyChangesToSync(FROM_HERE, changes_applied);
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ApplyChangesToDatabase(changes_applied);
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return true;
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void DomDistillerStore::AddObserver(DomDistillerObserver* observer) {
152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  observers_.AddObserver(observer);
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void DomDistillerStore::RemoveObserver(DomDistillerObserver* observer) {
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  observers_.RemoveObserver(observer);
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)std::vector<ArticleEntry> DomDistillerStore::GetEntries() const {
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return model_.GetEntries();
1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// syncer::SyncableService implementation.
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)SyncMergeResult DomDistillerStore::MergeDataAndStartSyncing(
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ModelType type, const SyncDataList& initial_sync_data,
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_ptr<syncer::SyncErrorFactory> error_handler) {
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_EQ(syncer::ARTICLES, type);
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!sync_processor_);
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!error_factory_);
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sync_processor_.reset(sync_processor.release());
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error_factory_.reset(error_handler.release());
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncChangeList database_changes;
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncChangeList sync_changes;
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncMergeResult result =
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      MergeDataWithModel(initial_sync_data, &database_changes, &sync_changes);
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ApplyChangesToDatabase(database_changes);
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ApplyChangesToSync(FROM_HERE, sync_changes);
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return result;
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DomDistillerStore::StopSyncing(ModelType type) {
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sync_processor_.reset();
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error_factory_.reset();
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)SyncDataList DomDistillerStore::GetAllSyncData(ModelType type) const {
1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return model_.GetAllSyncData();
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)SyncError DomDistillerStore::ProcessSyncChanges(
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const tracked_objects::Location& from_here,
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const SyncChangeList& change_list) {
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(database_loaded_);
1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncChangeList database_changes;
1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncChangeList sync_changes;
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ApplyChangesToModel(change_list, &database_changes, &sync_changes);
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ApplyChangesToDatabase(database_changes);
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_EQ(size_t(0), sync_changes.size());
2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return SyncError();
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void DomDistillerStore::NotifyObservers(const syncer::SyncChangeList& changes) {
206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (observers_.might_have_observers() && changes.size() > 0) {
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::vector<DomDistillerObserver::ArticleUpdate> article_changes;
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    for (SyncChangeList::const_iterator it = changes.begin();
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)         it != changes.end(); ++it) {
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DomDistillerObserver::ArticleUpdate article_update;
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      switch (it->change_type()) {
212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        case SyncChange::ACTION_ADD:
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          article_update.update_type = DomDistillerObserver::ArticleUpdate::ADD;
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          break;
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        case SyncChange::ACTION_UPDATE:
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          article_update.update_type =
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              DomDistillerObserver::ArticleUpdate::UPDATE;
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          break;
219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        case SyncChange::ACTION_DELETE:
220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          article_update.update_type =
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              DomDistillerObserver::ArticleUpdate::REMOVE;
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          break;
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        case SyncChange::ACTION_INVALID:
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          NOTREACHED();
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          break;
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const ArticleEntry& entry = GetEntryFromChange(*it);
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      article_update.entry_id = entry.entry_id();
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      article_changes.push_back(article_update);
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    FOR_EACH_OBSERVER(DomDistillerObserver, observers_,
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                      ArticleEntriesUpdated(article_changes));
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DomDistillerStore::ApplyChangesToModel(const SyncChangeList& changes,
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                            SyncChangeList* changes_applied,
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                            SyncChangeList* changes_missing) {
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  model_.ApplyChangesToModel(changes, changes_applied, changes_missing);
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  NotifyObservers(*changes_applied);
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DomDistillerStore::OnDatabaseInit(bool success) {
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!success) {
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "DOM Distiller database init failed.";
2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    database_.reset();
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  database_->LoadEntries(base::Bind(&DomDistillerStore::OnDatabaseLoad,
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                    weak_ptr_factory_.GetWeakPtr()));
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DomDistillerStore::OnDatabaseLoad(bool success,
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                       scoped_ptr<EntryVector> entries) {
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!success) {
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "DOM Distiller database load failed.";
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    database_.reset();
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  database_loaded_ = true;
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncDataList data;
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (EntryVector::iterator it = entries->begin(); it != entries->end();
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       ++it) {
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    data.push_back(CreateLocalData(*it));
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncChangeList changes_applied;
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncChangeList database_changes_needed;
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  MergeDataWithModel(data, &changes_applied, &database_changes_needed);
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ApplyChangesToDatabase(database_changes_needed);
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DomDistillerStore::OnDatabaseSave(bool success) {
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!success) {
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "DOM Distiller database save failed."
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             << " Disabling modifications and sync.";
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    database_.reset();
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    database_loaded_ = false;
2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    StopSyncing(syncer::ARTICLES);
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool DomDistillerStore::ApplyChangesToSync(
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const tracked_objects::Location& from_here,
2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const SyncChangeList& change_list) {
2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!sync_processor_) {
2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (change_list.empty()) {
2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncError error = sync_processor_->ProcessSyncChanges(from_here, change_list);
2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error.IsSet()) {
2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    StopSyncing(syncer::ARTICLES);
2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return true;
2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool DomDistillerStore::ApplyChangesToDatabase(
3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const SyncChangeList& change_list) {
3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!database_loaded_) {
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (change_list.empty()) {
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<ProtoDatabase<ArticleEntry>::KeyEntryVector> entries_to_save(
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      new ProtoDatabase<ArticleEntry>::KeyEntryVector());
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<std::vector<std::string> > keys_to_remove(
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      new std::vector<std::string>());
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (SyncChangeList::const_iterator it = change_list.begin();
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       it != change_list.end(); ++it) {
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (it->change_type() == SyncChange::ACTION_DELETE) {
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ArticleEntry entry = GetEntryFromChange(*it);
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      keys_to_remove->push_back(entry.entry_id());
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else {
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ArticleEntry entry = GetEntryFromChange(*it);
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      entries_to_save->push_back(std::make_pair(entry.entry_id(), entry));
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  database_->UpdateEntries(entries_to_save.Pass(), keys_to_remove.Pass(),
325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                           base::Bind(&DomDistillerStore::OnDatabaseSave,
326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                      weak_ptr_factory_.GetWeakPtr()));
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return true;
3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)SyncMergeResult DomDistillerStore::MergeDataWithModel(
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const SyncDataList& data, SyncChangeList* changes_applied,
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    SyncChangeList* changes_missing) {
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(changes_applied);
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(changes_missing);
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncMergeResult result(syncer::ARTICLES);
3371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  result.set_num_items_before_association(model_.GetNumEntries());
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SyncChangeList changes_to_apply;
3401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  model_.CalculateChangesForMerge(data, &changes_to_apply, changes_missing);
3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SyncError error;
342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ApplyChangesToModel(changes_to_apply, changes_applied, changes_missing);
3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int num_added = 0;
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int num_modified = 0;
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (SyncChangeList::const_iterator it = changes_applied->begin();
347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       it != changes_applied->end(); ++it) {
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK(it->IsValid());
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    switch (it->change_type()) {
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      case SyncChange::ACTION_ADD:
3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        num_added++;
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        break;
3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      case SyncChange::ACTION_UPDATE:
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        num_modified++;
3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        break;
3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      default:
3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        NOTREACHED();
3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  result.set_num_items_added(num_added);
3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  result.set_num_items_modified(num_modified);
3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  result.set_num_items_deleted(0);
3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  result.set_pre_association_version(0);
3651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  result.set_num_items_after_association(model_.GetNumEntries());
3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  result.set_error(error);
3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return result;
3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace dom_distiller
372