1// Copyright (c) 2012 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_SYNC_GLUE_TYPED_URL_CHANGE_PROCESSOR_H_
6#define CHROME_BROWSER_SYNC_GLUE_TYPED_URL_CHANGE_PROCESSOR_H_
7
8#include "components/sync_driver/change_processor.h"
9
10#include "base/basictypes.h"
11#include "base/compiler_specific.h"
12#include "base/memory/scoped_ptr.h"
13#include "chrome/browser/sync/glue/sync_backend_host.h"
14#include "chrome/browser/sync/glue/typed_url_model_associator.h"
15#include "components/sync_driver/data_type_error_handler.h"
16#include "content/public/browser/notification_observer.h"
17#include "content/public/browser/notification_registrar.h"
18#include "content/public/browser/notification_types.h"
19
20class Profile;
21
22namespace base {
23class MessageLoop;
24}
25
26namespace content {
27class NotificationService;
28}
29
30namespace history {
31class HistoryBackend;
32struct URLsDeletedDetails;
33struct URLsModifiedDetails;
34struct URLVisitedDetails;
35class URLRow;
36};
37
38namespace browser_sync {
39
40class DataTypeErrorHandler;
41
42// This class is responsible for taking changes from the history backend and
43// applying them to the sync API 'syncable' model, and vice versa. All
44// operations and use of this class are from the UI thread.
45class TypedUrlChangeProcessor : public sync_driver::ChangeProcessor,
46                                public content::NotificationObserver {
47 public:
48  TypedUrlChangeProcessor(Profile* profile,
49                          TypedUrlModelAssociator* model_associator,
50                          history::HistoryBackend* history_backend,
51                          sync_driver::DataTypeErrorHandler* error_handler);
52  virtual ~TypedUrlChangeProcessor();
53
54  // content::NotificationObserver implementation.
55  // History -> sync API change application.
56  virtual void Observe(int type,
57                       const content::NotificationSource& source,
58                       const content::NotificationDetails& details) OVERRIDE;
59
60  // sync API model -> WebDataService change application.
61  virtual void ApplyChangesFromSyncModel(
62      const syncer::BaseTransaction* trans,
63      int64 model_version,
64      const syncer::ImmutableChangeRecordList& changes) OVERRIDE;
65
66  // Commit changes here, after we've released the transaction lock to avoid
67  // jank.
68  virtual void CommitChangesFromSyncModel() OVERRIDE;
69
70  // Stop processing changes and wait for being destroyed.
71  void Disconnect();
72
73 protected:
74  virtual void StartImpl() OVERRIDE;
75
76 private:
77  friend class ScopedStopObserving<TypedUrlChangeProcessor>;
78  void StartObserving();
79  void StopObserving();
80
81  void HandleURLsModified(history::URLsModifiedDetails* details);
82  void HandleURLsDeleted(history::URLsDeletedDetails* details);
83  void HandleURLsVisited(history::URLVisitedDetails* details);
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(history::URLVisitedDetails* details);
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(history::URLRow typed_url,
95                              syncer::WriteTransaction* transaction);
96
97  // The profile with which we are associated.
98  Profile* profile_;
99
100  // The two models should be associated according to this ModelAssociator.
101  TypedUrlModelAssociator* model_associator_;
102
103  // The model we are processing changes from.  This is owned by the
104  // WebDataService which is kept alive by our data type controller
105  // holding a reference.
106  history::HistoryBackend* history_backend_;
107  base::MessageLoop* backend_loop_;
108
109  content::NotificationRegistrar notification_registrar_;
110
111  scoped_ptr<content::NotificationService> notification_service_;
112
113  // The set of pending changes that will be written out on the next
114  // CommitChangesFromSyncModel() call.
115  history::URLRows pending_new_urls_;
116  history::URLRows pending_updated_urls_;
117  std::vector<GURL> pending_deleted_urls_;
118  TypedUrlModelAssociator::TypedUrlVisitVector pending_new_visits_;
119  history::VisitVector pending_deleted_visits_;
120
121  bool disconnected_;
122  base::Lock disconnect_lock_;
123
124  DISALLOW_COPY_AND_ASSIGN(TypedUrlChangeProcessor);
125};
126
127}  // namespace browser_sync
128
129#endif  // CHROME_BROWSER_SYNC_GLUE_TYPED_URL_CHANGE_PROCESSOR_H_
130