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/common/page_transition_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 expired, 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