Home | History | Annotate | Download | only in history
      1 // Copyright (c) 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 CHROME_BROWSER_HISTORY_TYPED_URL_SYNCABLE_SERVICE_H_
      6 #define CHROME_BROWSER_HISTORY_TYPED_URL_SYNCABLE_SERVICE_H_
      7 
      8 #include <set>
      9 #include <vector>
     10 
     11 #include "chrome/browser/history/history_notifications.h"
     12 #include "chrome/browser/history/history_types.h"
     13 #include "content/public/browser/notification_types.h"
     14 #include "sync/api/sync_change.h"
     15 #include "sync/api/sync_data.h"
     16 #include "sync/api/sync_error.h"
     17 #include "sync/api/sync_error_factory.h"
     18 #include "sync/api/syncable_service.h"
     19 
     20 class GURL;
     21 class TypedUrlSyncableServiceTest;
     22 
     23 namespace base {
     24 class MessageLoop;
     25 };
     26 
     27 namespace sync_pb {
     28 class TypedUrlSpecifics;
     29 };
     30 
     31 namespace history {
     32 
     33 class HistoryBackend;
     34 class URLRow;
     35 
     36 extern const char kTypedUrlTag[];
     37 
     38 class TypedUrlSyncableService : public syncer::SyncableService {
     39  public:
     40   explicit TypedUrlSyncableService(HistoryBackend* history_backend);
     41   virtual ~TypedUrlSyncableService();
     42 
     43   static syncer::ModelType model_type() { return syncer::TYPED_URLS; }
     44 
     45   // syncer::SyncableService implementation.
     46   virtual syncer::SyncMergeResult MergeDataAndStartSyncing(
     47       syncer::ModelType type,
     48       const syncer::SyncDataList& initial_sync_data,
     49       scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
     50       scoped_ptr<syncer::SyncErrorFactory> error_handler) OVERRIDE;
     51   virtual void StopSyncing(syncer::ModelType type) OVERRIDE;
     52   virtual syncer::SyncDataList GetAllSyncData(
     53       syncer::ModelType type) const OVERRIDE;
     54   virtual syncer::SyncError ProcessSyncChanges(
     55       const tracked_objects::Location& from_here,
     56       const syncer::SyncChangeList& change_list) OVERRIDE;
     57 
     58   // Called directly by HistoryBackend when local url data changes.
     59   void OnUrlsModified(URLRows* changed_urls);
     60   void OnUrlVisited(content::PageTransition transition, URLRow* row);
     61   void OnUrlsDeleted(bool all_history, bool archived, URLRows* rows);
     62 
     63  protected:
     64   void GetSyncedUrls(std::set<GURL>* urls) {
     65     urls->insert(synced_typed_urls_.begin(), synced_typed_urls_.end());
     66   }
     67 
     68  private:
     69   typedef std::vector<std::pair<URLID, URLRow> > TypedUrlUpdateVector;
     70   typedef std::vector<std::pair<GURL, std::vector<VisitInfo> > >
     71       TypedUrlVisitVector;
     72 
     73   // This is a helper map used only in Merge/Process* functions. The lifetime
     74   // of the iterator is longer than the map object.
     75   typedef std::map<GURL, std::pair<syncer::SyncChange::SyncChangeType,
     76                                    URLRows::iterator> > TypedUrlMap;
     77   // This is a helper map used to associate visit vectors from the history db
     78   // to the typed urls in the above map.
     79   typedef std::map<GURL, VisitVector> UrlVisitVectorMap;
     80 
     81   // Helper function that determines if we should ignore a URL for the purposes
     82   // of sync, because it contains invalid data.
     83   bool ShouldIgnoreUrl(const GURL& url);
     84 
     85   // Returns true if the caller should sync as a result of the passed visit
     86   // notification. We use this to throttle the number of sync changes we send
     87   // to the server so we don't hit the server for every
     88   // single typed URL visit.
     89   bool ShouldSyncVisit(content::PageTransition transition, URLRow* row);
     90 
     91   // Utility routine that either updates an existing sync node or creates a
     92   // new one for the passed |typed_url| if one does not already exist. Returns
     93   // false and sets an unrecoverable error if the operation failed.
     94   bool CreateOrUpdateSyncNode(URLRow typed_url,
     95                               syncer::SyncChangeList* changes);
     96 
     97   void AddTypedUrlToChangeList(
     98     syncer::SyncChange::SyncChangeType change_type,
     99     const URLRow& row,
    100     const VisitVector& visits,
    101     std::string title,
    102     syncer::SyncChangeList* change_list);
    103 
    104   // Converts the passed URL information to a TypedUrlSpecifics structure for
    105   // writing to the sync DB.
    106   static void WriteToTypedUrlSpecifics(const URLRow& url,
    107                                        const VisitVector& visits,
    108                                        sync_pb::TypedUrlSpecifics* specifics);
    109 
    110   // Fetches visits from the history DB corresponding to the passed URL. This
    111   // function compensates for the fact that the history DB has rather poor data
    112   // integrity (duplicate visits, visit timestamps that don't match the
    113   // last_visit timestamp, huge data sets that exhaust memory when fetched,
    114   // etc) by modifying the passed |url| object and |visits| vector.
    115   // Returns false if we could not fetch the visits for the passed URL, and
    116   // tracks DB error statistics internally for reporting via UMA.
    117   virtual bool FixupURLAndGetVisits(URLRow* url,
    118                                     VisitVector* visits);
    119 
    120   // TODO(sync): Consider using "delete all" sync logic instead of in-memory
    121   // cache of typed urls. See http://crbug.com/231689.
    122   std::set<GURL> synced_typed_urls_;
    123 
    124   HistoryBackend* const history_backend_;
    125 
    126   // Whether we're currently processing changes from the syncer. While this is
    127   // true, we ignore any local url changes, since we triggered them.
    128   bool processing_syncer_changes_;
    129 
    130   // We receive ownership of |sync_processor_| and |error_handler_| in
    131   // MergeDataAndStartSyncing() and destroy them in StopSyncing().
    132   scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
    133   scoped_ptr<syncer::SyncErrorFactory> sync_error_handler_;
    134 
    135   // Statistics for the purposes of tracking the percentage of DB accesses that
    136   // fail for each client via UMA.
    137   int num_db_accesses_;
    138   int num_db_errors_;
    139 
    140   base::MessageLoop* expected_loop_;
    141 
    142   FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
    143                            AddLocalTypedUrlAndSync);
    144   FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
    145                            UpdateLocalTypedUrlAndSync);
    146   FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
    147                            LinkVisitLocalTypedUrlAndSync);
    148   FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
    149                            TypedVisitLocalTypedUrlAndSync);
    150   FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
    151                            DeleteLocalTypedUrlAndSync);
    152   FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
    153                            DeleteAllLocalTypedUrlAndSync);
    154   FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
    155                            MaxVisitLocalTypedUrlAndSync);
    156   FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
    157                            ThrottleVisitLocalTypedUrlSync);
    158 
    159   DISALLOW_COPY_AND_ASSIGN(TypedUrlSyncableService);
    160 };
    161 
    162 }  // namespace history
    163 
    164 #endif  // CHROME_BROWSER_HISTORY_TYPED_URL_SYNCABLE_SERVICE_H_
    165