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 "components/history/core/browser/history_types.h"
13 #include "sync/api/sync_change.h"
14 #include "sync/api/sync_data.h"
15 #include "sync/api/sync_error.h"
16 #include "sync/api/sync_error_factory.h"
17 #include "sync/api/syncable_service.h"
18 #include "ui/base/page_transition_types.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 ~TypedUrlSyncableService() override;
43 static syncer::ModelType model_type() { return syncer::TYPED_URLS; }
45 // syncer::SyncableService implementation.
46 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 void StopSyncing(syncer::ModelType type) override;
52 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
53 syncer::SyncError ProcessSyncChanges(
54 const tracked_objects::Location& from_here,
55 const syncer::SyncChangeList& change_list) override;
57 // Called directly by HistoryBackend when local url data changes.
58 void OnUrlsModified(URLRows* changed_urls);
59 void OnUrlVisited(ui::PageTransition transition, URLRow* row);
60 void OnUrlsDeleted(bool all_history, bool expired, URLRows* rows);
63 void GetSyncedUrls(std::set<GURL>* urls) {
64 urls->insert(synced_typed_urls_.begin(), synced_typed_urls_.end());
68 typedef std::vector<std::pair<URLID, URLRow> > TypedUrlUpdateVector;
69 typedef std::vector<std::pair<GURL, std::vector<VisitInfo> > >
72 // This is a helper map used only in Merge/Process* functions. The lifetime
73 // of the iterator is longer than the map object.
74 typedef std::map<GURL, std::pair<syncer::SyncChange::SyncChangeType,
75 URLRows::iterator> > TypedUrlMap;
76 // This is a helper map used to associate visit vectors from the history db
77 // to the typed urls in the above map.
78 typedef std::map<GURL, VisitVector> UrlVisitVectorMap;
80 // Helper function that determines if we should ignore a URL for the purposes
81 // of sync, because it contains invalid data.
82 bool ShouldIgnoreUrl(const GURL& url);
84 // Returns true if the caller should sync as a result of the passed visit
85 // notification. We use this to throttle the number of sync changes we send
86 // to the server so we don't hit the server for every
87 // single typed URL visit.
88 bool ShouldSyncVisit(ui::PageTransition transition, URLRow* row);
90 // Utility routine that either updates an existing sync node or creates a
91 // new one for the passed |typed_url| if one does not already exist. Returns
92 // false and sets an unrecoverable error if the operation failed.
93 bool CreateOrUpdateSyncNode(URLRow typed_url,
94 syncer::SyncChangeList* changes);
96 void AddTypedUrlToChangeList(
97 syncer::SyncChange::SyncChangeType change_type,
99 const VisitVector& visits,
101 syncer::SyncChangeList* change_list);
103 // Converts the passed URL information to a TypedUrlSpecifics structure for
104 // writing to the sync DB.
105 static void WriteToTypedUrlSpecifics(const URLRow& url,
106 const VisitVector& visits,
107 sync_pb::TypedUrlSpecifics* specifics);
109 // Fetches visits from the history DB corresponding to the passed URL. This
110 // function compensates for the fact that the history DB has rather poor data
111 // integrity (duplicate visits, visit timestamps that don't match the
112 // last_visit timestamp, huge data sets that exhaust memory when fetched,
113 // etc) by modifying the passed |url| object and |visits| vector.
114 // Returns false if we could not fetch the visits for the passed URL, and
115 // tracks DB error statistics internally for reporting via UMA.
116 virtual bool FixupURLAndGetVisits(URLRow* url,
117 VisitVector* visits);
119 // TODO(sync): Consider using "delete all" sync logic instead of in-memory
120 // cache of typed urls. See http://crbug.com/231689.
121 std::set<GURL> synced_typed_urls_;
123 HistoryBackend* const history_backend_;
125 // Whether we're currently processing changes from the syncer. While this is
126 // true, we ignore any local url changes, since we triggered them.
127 bool processing_syncer_changes_;
129 // We receive ownership of |sync_processor_| and |error_handler_| in
130 // MergeDataAndStartSyncing() and destroy them in StopSyncing().
131 scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
132 scoped_ptr<syncer::SyncErrorFactory> sync_error_handler_;
134 // Statistics for the purposes of tracking the percentage of DB accesses that
135 // fail for each client via UMA.
136 int num_db_accesses_;
139 base::MessageLoop* expected_loop_;
141 FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
142 AddLocalTypedUrlAndSync);
143 FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
144 UpdateLocalTypedUrlAndSync);
145 FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
146 LinkVisitLocalTypedUrlAndSync);
147 FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
148 TypedVisitLocalTypedUrlAndSync);
149 FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
150 DeleteLocalTypedUrlAndSync);
151 FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
152 DeleteAllLocalTypedUrlAndSync);
153 FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
154 MaxVisitLocalTypedUrlAndSync);
155 FRIEND_TEST_ALL_PREFIXES(TypedUrlSyncableServiceTest,
156 ThrottleVisitLocalTypedUrlSync);
158 DISALLOW_COPY_AND_ASSIGN(TypedUrlSyncableService);
161 } // namespace history
163 #endif // CHROME_BROWSER_HISTORY_TYPED_URL_SYNCABLE_SERVICE_H_