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.
5 #ifndef CHROME_BROWSER_HISTORY_TYPED_URL_SYNCABLE_SERVICE_H_
6 #define CHROME_BROWSER_HISTORY_TYPED_URL_SYNCABLE_SERVICE_H_
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"
21 class TypedUrlSyncableServiceTest;
28 class TypedUrlSpecifics;
36 extern const char kTypedUrlTag[];
38 class TypedUrlSyncableService : public syncer::SyncableService {
40 explicit TypedUrlSyncableService(HistoryBackend* history_backend);
41 virtual ~TypedUrlSyncableService();
43 static syncer::ModelType model_type() { return syncer::TYPED_URLS; }
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;
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);
64 void GetSyncedUrls(std::set<GURL>* urls) {
65 urls->insert(synced_typed_urls_.begin(), synced_typed_urls_.end());
69 typedef std::vector<std::pair<URLID, URLRow> > TypedUrlUpdateVector;
70 typedef std::vector<std::pair<GURL, std::vector<VisitInfo> > >
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;
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);
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);
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);
97 void AddTypedUrlToChangeList(
98 syncer::SyncChange::SyncChangeType change_type,
100 const VisitVector& visits,
102 syncer::SyncChangeList* change_list);
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);
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);
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_;
124 HistoryBackend* const history_backend_;
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_;
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_;
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_;
140 base::MessageLoop* expected_loop_;
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);
159 DISALLOW_COPY_AND_ASSIGN(TypedUrlSyncableService);
162 } // namespace history
164 #endif // CHROME_BROWSER_HISTORY_TYPED_URL_SYNCABLE_SERVICE_H_