root/chrome/browser/history/typed_url_syncable_service.h

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

INCLUDED FROM


// Copyright (c) 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 CHROME_BROWSER_HISTORY_TYPED_URL_SYNCABLE_SERVICE_H_
#define CHROME_BROWSER_HISTORY_TYPED_URL_SYNCABLE_SERVICE_H_

#include <set>
#include <vector>

#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/history_types.h"
#include "content/public/browser/notification_types.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/syncable_service.h"

class GURL;
class TypedUrlSyncableServiceTest;

namespace base {
class MessageLoop;
};

namespace sync_pb {
class TypedUrlSpecifics;
};

namespace history {

class HistoryBackend;
class URLRow;

extern const char kTypedUrlTag[];

class TypedUrlSyncableService : public syncer::SyncableService {
 public:
  explicit TypedUrlSyncableService(HistoryBackend* history_backend);
  virtual ~TypedUrlSyncableService();

  static syncer::ModelType model_type() { return syncer::TYPED_URLS; }

  // 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;

  // Called directly by HistoryBackend when local url data changes.
  void OnUrlsModified(URLRows* changed_urls);
  void OnUrlVisited(content::PageTransition transition, URLRow* row);
  void OnUrlsDeleted(bool all_history, bool archived, URLRows* rows);

 protected:
  void GetSyncedUrls(std::set<GURL>* urls) {
    urls->insert(synced_typed_urls_.begin(), synced_typed_urls_.end());
  }

 private:
  typedef std::vector<std::pair<URLID, URLRow> > TypedUrlUpdateVector;
  typedef std::vector<std::pair<GURL, std::vector<VisitInfo> > >
      TypedUrlVisitVector;

  // This is a helper map used only in Merge/Process* functions. The lifetime
  // of the iterator is longer than the map object.
  typedef std::map<GURL, std::pair<syncer::SyncChange::SyncChangeType,
                                   URLRows::iterator> > TypedUrlMap;
  // This is a helper map used to associate visit vectors from the history db
  // to the typed urls in the above map.
  typedef std::map<GURL, VisitVector> UrlVisitVectorMap;

  // Helper function that determines if we should ignore a URL for the purposes
  // of sync, because it contains invalid data.
  bool ShouldIgnoreUrl(const GURL& url);

  // Returns true if the caller should sync as a result of the passed visit
  // notification. We use this to throttle the number of sync changes we send
  // to the server so we don't hit the server for every
  // single typed URL visit.
  bool ShouldSyncVisit(content::PageTransition transition, URLRow* row);

  // Utility routine that either updates an existing sync node or creates a
  // new one for the passed |typed_url| if one does not already exist. Returns
  // false and sets an unrecoverable error if the operation failed.
  bool CreateOrUpdateSyncNode(URLRow typed_url,
                              syncer::SyncChangeList* changes);

  void AddTypedUrlToChangeList(
    syncer::SyncChange::SyncChangeType change_type,
    const URLRow& row,
    const VisitVector& visits,
    std::string title,
    syncer::SyncChangeList* change_list);

  // Converts the passed URL information to a TypedUrlSpecifics structure for
  // writing to the sync DB.
  static void WriteToTypedUrlSpecifics(const URLRow& url,
                                       const VisitVector& visits,
                                       sync_pb::TypedUrlSpecifics* specifics);

  // Fetches visits from the history DB corresponding to the passed URL. This
  // function compensates for the fact that the history DB has rather poor data
  // integrity (duplicate visits, visit timestamps that don't match the
  // last_visit timestamp, huge data sets that exhaust memory when fetched,
  // etc) by modifying the passed |url| object and |visits| vector.
  // Returns false if we could not fetch the visits for the passed URL, and
  // tracks DB error statistics internally for reporting via UMA.
  virtual bool FixupURLAndGetVisits(URLRow* url,
                                    VisitVector* visits);

  // TODO(sync): Consider using "delete all" sync logic instead of in-memory
  // cache of typed urls. See http://crbug.com/231689.
  std::set<GURL> synced_typed_urls_;

  HistoryBackend* const history_backend_;

  // Whether we're currently processing changes from the syncer. While this is
  // true, we ignore any local url changes, since we triggered them.
  bool processing_syncer_changes_;

  // We receive ownership of |sync_processor_| and |error_handler_| in
  // MergeDataAndStartSyncing() and destroy them in StopSyncing().
  scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
  scoped_ptr<syncer::SyncErrorFactory> sync_error_handler_;

  // Statistics for the purposes of tracking the percentage of DB accesses that
  // fail for each client via UMA.
  int num_db_accesses_;
  int num_db_errors_;

  base::MessageLoop* expected_loop_;

  FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
                           AddLocalTypedUrlAndSync);
  FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
                           UpdateLocalTypedUrlAndSync);
  FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
                           LinkVisitLocalTypedUrlAndSync);
  FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
                           TypedVisitLocalTypedUrlAndSync);
  FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
                           DeleteLocalTypedUrlAndSync);
  FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
                           DeleteAllLocalTypedUrlAndSync);
  FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
                           MaxVisitLocalTypedUrlAndSync);
  FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
                           ThrottleVisitLocalTypedUrlSync);

  DISALLOW_COPY_AND_ASSIGN(TypedUrlSyncableService);
};

}  // namespace history

#endif  // CHROME_BROWSER_HISTORY_TYPED_URL_SYNCABLE_SERVICE_H_

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