root/components/dom_distiller/core/dom_distiller_store.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_STORE_H_
#define COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_STORE_H_

#include <string>
#include <vector>

#include "base/containers/hash_tables.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "components/dom_distiller/core/article_entry.h"
#include "components/dom_distiller/core/dom_distiller_database.h"
#include "components/dom_distiller/core/dom_distiller_model.h"
#include "components/dom_distiller/core/dom_distiller_observer.h"
#include "sync/api/sync_change.h"
#include "sync/api/sync_data.h"
#include "sync/api/sync_error.h"
#include "sync/api/sync_error_factory.h"
#include "sync/api/sync_merge_result.h"
#include "sync/api/syncable_service.h"
#include "url/gurl.h"

namespace base {
class FilePath;
}

namespace dom_distiller {

// Interface for accessing the stored/synced DomDistiller entries.
class DomDistillerStoreInterface {
 public:
  virtual ~DomDistillerStoreInterface() {}

  // Gets the syncable service for this store or null if it is not synced.
  virtual syncer::SyncableService* GetSyncableService() = 0;

  virtual bool AddEntry(const ArticleEntry& entry) = 0;

  // Returns false if |entry| is not present or |entry| was not updated.
  virtual bool UpdateEntry(const ArticleEntry& entry) = 0;

  virtual bool RemoveEntry(const ArticleEntry& entry) = 0;

  // Lookup an ArticleEntry by ID or URL. Returns whether a corresponding entry
  // was found. On success, if |entry| is not null, it will contain the entry.
  virtual bool GetEntryById(const std::string& entry_id,
                            ArticleEntry* entry) = 0;
  virtual bool GetEntryByUrl(const GURL& url, ArticleEntry* entry) = 0;

  // Gets a copy of all the current entries.
  virtual std::vector<ArticleEntry> GetEntries() const = 0;

  virtual void AddObserver(DomDistillerObserver* observer) = 0;

  virtual void RemoveObserver(DomDistillerObserver* observer) = 0;
};

// Implements syncing/storing of DomDistiller entries. This keeps three
// models of the DOM distiller data in sync: the local database, sync, and the
// user (i.e. of DomDistillerStore). No changes are accepted while the local
// database is loading. Once the local database has loaded, changes from any of
// the three sources (technically just two, since changes don't come from the
// database) are handled similarly:
// 1. convert the change to a SyncChangeList.
// 2. apply that change to the in-memory model, calculating what changed
// (changes_applied) and what is missing--i.e. entries missing for a full merge,
// conflict resolution for normal changes-- (changes_missing).
// 3. send a message (possibly handled asynchronously) containing
// changes_missing to the source of the change.
// 4. send messages (possibly handled asynchronously) containing changes_applied
// to the other (i.e. non-source) two models.
// TODO(cjhopman): Support deleting entries.
class DomDistillerStore : public syncer::SyncableService,
                          public DomDistillerStoreInterface {
 public:
  // Creates storage using the given database for local storage. Initializes the
  // database with |database_dir|.
  DomDistillerStore(scoped_ptr<DomDistillerDatabaseInterface> database,
                    const base::FilePath& database_dir);

  // Creates storage using the given database for local storage. Initializes the
  // database with |database_dir|.  Also initializes the internal model to
  // |initial_model|.
  DomDistillerStore(scoped_ptr<DomDistillerDatabaseInterface> database,
                    const std::vector<ArticleEntry>& initial_data,
                    const base::FilePath& database_dir);

  virtual ~DomDistillerStore();

  // DomDistillerStoreInterface implementation.
  virtual syncer::SyncableService* GetSyncableService() OVERRIDE;
  virtual bool AddEntry(const ArticleEntry& entry) OVERRIDE;
  virtual bool UpdateEntry(const ArticleEntry& entry) OVERRIDE;
  virtual bool RemoveEntry(const ArticleEntry& entry) OVERRIDE;
  virtual bool GetEntryById(const std::string& entry_id,
                            ArticleEntry* entry) OVERRIDE;
  virtual bool GetEntryByUrl(const GURL& url, ArticleEntry* entry) OVERRIDE;
  virtual std::vector<ArticleEntry> GetEntries() const OVERRIDE;
  virtual void AddObserver(DomDistillerObserver* observer) OVERRIDE;
  virtual void RemoveObserver(DomDistillerObserver* observer) OVERRIDE;

  // syncer::SyncableService implementation.
  virtual syncer::SyncMergeResult MergeDataAndStartSyncing(
      syncer::ModelType type,
      const syncer::SyncDataList& initial_sync_data,
      scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
      scoped_ptr<syncer::SyncErrorFactory> error_handler) OVERRIDE;
  virtual void StopSyncing(syncer::ModelType type) OVERRIDE;
  virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
      OVERRIDE;
  virtual syncer::SyncError ProcessSyncChanges(
      const tracked_objects::Location& from_here,
      const syncer::SyncChangeList& change_list) OVERRIDE;
 private:
  void OnDatabaseInit(bool success);
  void OnDatabaseLoad(bool success, scoped_ptr<EntryVector> entries);
  void OnDatabaseSave(bool success);

  syncer::SyncMergeResult MergeDataWithModel(
      const syncer::SyncDataList& data,
      syncer::SyncChangeList* changes_applied,
      syncer::SyncChangeList* changes_missing);

  // Convert a SyncDataList to a SyncChangeList of add or update changes based
  // on the state of the in-memory model. Also calculate the entries missing
  // from the SyncDataList.
  void CalculateChangesForMerge(const syncer::SyncDataList& data,
                                syncer::SyncChangeList* changes_to_apply,
                                syncer::SyncChangeList* changes_missing);

  bool ApplyChangesToSync(const tracked_objects::Location& from_here,
                          const syncer::SyncChangeList& change_list);
  bool ApplyChangesToDatabase(const syncer::SyncChangeList& change_list);

  // Applies the changes to |model_|. If the model returns an error, disables
  // syncing and database changes and returns false.
  void ApplyChangesToModel(const syncer::SyncChangeList& change_list,
                           syncer::SyncChangeList* changes_applied,
                           syncer::SyncChangeList* changes_missing);

  void NotifyObservers(const syncer::SyncChangeList& changes);

  scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
  scoped_ptr<syncer::SyncErrorFactory> error_factory_;
  scoped_ptr<DomDistillerDatabaseInterface> database_;
  bool database_loaded_;
  ObserverList<DomDistillerObserver> observers_;

  DomDistillerModel model_;

  base::WeakPtrFactory<DomDistillerStore> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(DomDistillerStore);
};

}  // namespace dom_distiller

#endif  // COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_STORE_H_

/* [<][>][^][v][top][bottom][index][help] */