Home | History | Annotate | Download | only in core
      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 
     26 namespace base {
     27 class FilePath;
     28 }
     29 
     30 namespace dom_distiller {
     31 
     32 // Interface for accessing the stored/synced DomDistiller entries.
     33 class 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.
     76 class 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