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