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 3// found in the LICENSE file. 4 5#ifndef COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_STORE_H_ 6#define COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_STORE_H_ 7 8#include <string> 9#include <vector> 10 11#include "base/containers/hash_tables.h" 12#include "base/memory/weak_ptr.h" 13#include "base/observer_list.h" 14#include "components/dom_distiller/core/article_entry.h" 15#include "components/dom_distiller/core/dom_distiller_model.h" 16#include "components/dom_distiller/core/dom_distiller_observer.h" 17#include "components/leveldb_proto/proto_database.h" 18#include "sync/api/sync_change.h" 19#include "sync/api/sync_data.h" 20#include "sync/api/sync_error.h" 21#include "sync/api/sync_error_factory.h" 22#include "sync/api/sync_merge_result.h" 23#include "sync/api/syncable_service.h" 24#include "url/gurl.h" 25 26namespace base { 27class FilePath; 28} 29 30namespace dom_distiller { 31 32// Interface for accessing the stored/synced DomDistiller entries. 33class DomDistillerStoreInterface { 34 public: 35 virtual ~DomDistillerStoreInterface() {} 36 37 // Gets the syncable service for this store or null if it is not synced. 38 virtual syncer::SyncableService* GetSyncableService() = 0; 39 40 virtual bool AddEntry(const ArticleEntry& entry) = 0; 41 42 // Returns false if |entry| is not present or |entry| was not updated. 43 virtual bool UpdateEntry(const ArticleEntry& entry) = 0; 44 45 virtual bool RemoveEntry(const ArticleEntry& entry) = 0; 46 47 // Lookup an ArticleEntry by ID or URL. Returns whether a corresponding entry 48 // was found. On success, if |entry| is not null, it will contain the entry. 49 virtual bool GetEntryById(const std::string& entry_id, 50 ArticleEntry* entry) = 0; 51 virtual bool GetEntryByUrl(const GURL& url, ArticleEntry* entry) = 0; 52 53 // Gets a copy of all the current entries. 54 virtual std::vector<ArticleEntry> GetEntries() const = 0; 55 56 virtual void AddObserver(DomDistillerObserver* observer) = 0; 57 58 virtual void RemoveObserver(DomDistillerObserver* observer) = 0; 59}; 60 61// Implements syncing/storing of DomDistiller entries. This keeps three 62// models of the DOM distiller data in sync: the local database, sync, and the 63// user (i.e. of DomDistillerStore). No changes are accepted while the local 64// database is loading. Once the local database has loaded, changes from any of 65// the three sources (technically just two, since changes don't come from the 66// database) are handled similarly: 67// 1. convert the change to a SyncChangeList. 68// 2. apply that change to the in-memory model, calculating what changed 69// (changes_applied) and what is missing--i.e. entries missing for a full merge, 70// conflict resolution for normal changes-- (changes_missing). 71// 3. send a message (possibly handled asynchronously) containing 72// changes_missing to the source of the change. 73// 4. send messages (possibly handled asynchronously) containing changes_applied 74// to the other (i.e. non-source) two models. 75// TODO(cjhopman): Support deleting entries. 76class DomDistillerStore : public syncer::SyncableService, 77 public DomDistillerStoreInterface { 78 public: 79 typedef std::vector<ArticleEntry> EntryVector; 80 81 // Creates storage using the given database for local storage. Initializes the 82 // database with |database_dir|. 83 DomDistillerStore( 84 scoped_ptr<leveldb_proto::ProtoDatabase<ArticleEntry> > database, 85 const base::FilePath& database_dir); 86 87 // Creates storage using the given database for local storage. Initializes the 88 // database with |database_dir|. Also initializes the internal model to 89 // |initial_model|. 90 DomDistillerStore( 91 scoped_ptr<leveldb_proto::ProtoDatabase<ArticleEntry> > database, 92 const std::vector<ArticleEntry>& initial_data, 93 const base::FilePath& database_dir); 94 95 virtual ~DomDistillerStore(); 96 97 // DomDistillerStoreInterface implementation. 98 virtual syncer::SyncableService* GetSyncableService() OVERRIDE; 99 virtual bool AddEntry(const ArticleEntry& entry) OVERRIDE; 100 virtual bool UpdateEntry(const ArticleEntry& entry) OVERRIDE; 101 virtual bool RemoveEntry(const ArticleEntry& entry) OVERRIDE; 102 virtual bool GetEntryById(const std::string& entry_id, 103 ArticleEntry* entry) OVERRIDE; 104 virtual bool GetEntryByUrl(const GURL& url, ArticleEntry* entry) OVERRIDE; 105 virtual std::vector<ArticleEntry> GetEntries() const OVERRIDE; 106 virtual void AddObserver(DomDistillerObserver* observer) OVERRIDE; 107 virtual void RemoveObserver(DomDistillerObserver* observer) OVERRIDE; 108 109 // syncer::SyncableService implementation. 110 virtual syncer::SyncMergeResult MergeDataAndStartSyncing( 111 syncer::ModelType type, const syncer::SyncDataList& initial_sync_data, 112 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 113 scoped_ptr<syncer::SyncErrorFactory> error_handler) OVERRIDE; 114 virtual void StopSyncing(syncer::ModelType type) OVERRIDE; 115 virtual syncer::SyncDataList GetAllSyncData( 116 syncer::ModelType type) const OVERRIDE; 117 virtual syncer::SyncError ProcessSyncChanges( 118 const tracked_objects::Location& from_here, 119 const syncer::SyncChangeList& change_list) OVERRIDE; 120 121 private: 122 void OnDatabaseInit(bool success); 123 void OnDatabaseLoad(bool success, scoped_ptr<EntryVector> entries); 124 void OnDatabaseSave(bool success); 125 126 syncer::SyncMergeResult MergeDataWithModel( 127 const syncer::SyncDataList& data, syncer::SyncChangeList* changes_applied, 128 syncer::SyncChangeList* changes_missing); 129 130 // Convert a SyncDataList to a SyncChangeList of add or update changes based 131 // on the state of the in-memory model. Also calculate the entries missing 132 // from the SyncDataList. 133 void CalculateChangesForMerge(const syncer::SyncDataList& data, 134 syncer::SyncChangeList* changes_to_apply, 135 syncer::SyncChangeList* changes_missing); 136 137 bool ApplyChangesToSync(const tracked_objects::Location& from_here, 138 const syncer::SyncChangeList& change_list); 139 bool ApplyChangesToDatabase(const syncer::SyncChangeList& change_list); 140 141 // Applies the changes to |model_|. If the model returns an error, disables 142 // syncing and database changes and returns false. 143 void ApplyChangesToModel(const syncer::SyncChangeList& change_list, 144 syncer::SyncChangeList* changes_applied, 145 syncer::SyncChangeList* changes_missing); 146 147 void NotifyObservers(const syncer::SyncChangeList& changes); 148 149 scoped_ptr<syncer::SyncChangeProcessor> sync_processor_; 150 scoped_ptr<syncer::SyncErrorFactory> error_factory_; 151 scoped_ptr<leveldb_proto::ProtoDatabase<ArticleEntry> > database_; 152 bool database_loaded_; 153 ObserverList<DomDistillerObserver> observers_; 154 155 DomDistillerModel model_; 156 157 base::WeakPtrFactory<DomDistillerStore> weak_ptr_factory_; 158 159 DISALLOW_COPY_AND_ASSIGN(DomDistillerStore); 160}; 161 162} // namespace dom_distiller 163 164#endif // COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_STORE_H_ 165