summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync/glue/typed_url_change_processor.h
blob: f77294bbb98e27f984750f50658cb8138369cbe0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright (c) 2012 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_SYNC_GLUE_TYPED_URL_CHANGE_PROCESSOR_H_
#define CHROME_BROWSER_SYNC_GLUE_TYPED_URL_CHANGE_PROCESSOR_H_

#include "components/sync_driver/change_processor.h"

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/sync/glue/sync_backend_host.h"
#include "chrome/browser/sync/glue/typed_url_model_associator.h"
#include "components/history/core/browser/history_backend_observer.h"
#include "components/sync_driver/data_type_error_handler.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_types.h"

class Profile;

namespace base {
class MessageLoop;
}

namespace content {
class NotificationService;
}

namespace history {
class HistoryBackend;
struct URLsDeletedDetails;
struct URLsModifiedDetails;
struct URLVisitedDetails;
class URLRow;
};

namespace browser_sync {

class DataTypeErrorHandler;

// This class is responsible for taking changes from the history backend and
// applying them to the sync API 'syncable' model, and vice versa. All
// operations and use of this class are from the UI thread.
class TypedUrlChangeProcessor : public sync_driver::ChangeProcessor,
                                public content::NotificationObserver,
                                public history::HistoryBackendObserver {
 public:
  TypedUrlChangeProcessor(Profile* profile,
                          TypedUrlModelAssociator* model_associator,
                          history::HistoryBackend* history_backend,
                          sync_driver::DataTypeErrorHandler* error_handler);
  virtual ~TypedUrlChangeProcessor();

  // content::NotificationObserver implementation.
  // History -> sync API change application.
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) override;

  // history::HistoryBackendObserver:
  virtual void OnURLVisited(history::HistoryBackend* history_backend,
                            ui::PageTransition transition,
                            const history::URLRow& row,
                            const history::RedirectList& redirects,
                            base::Time visit_time) override;

  // sync API model -> WebDataService change application.
  virtual void ApplyChangesFromSyncModel(
      const syncer::BaseTransaction* trans,
      int64 model_version,
      const syncer::ImmutableChangeRecordList& changes) override;

  // Commit changes here, after we've released the transaction lock to avoid
  // jank.
  virtual void CommitChangesFromSyncModel() override;

  // Stop processing changes and wait for being destroyed.
  void Disconnect();

 protected:
  virtual void StartImpl() override;

 private:
  friend class ScopedStopObserving<TypedUrlChangeProcessor>;
  void StartObserving();
  void StopObserving();

  void HandleURLsModified(history::URLsModifiedDetails* details);
  void HandleURLsDeleted(history::URLsDeletedDetails* details);

  // 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(int typed_count, ui::PageTransition transition);

  // 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(history::URLRow typed_url,
                              syncer::WriteTransaction* transaction);

  // The profile with which we are associated.
  Profile* profile_;

  // The two models should be associated according to this ModelAssociator.
  TypedUrlModelAssociator* model_associator_;

  // The model we are processing changes from.  This is owned by the
  // WebDataService which is kept alive by our data type controller
  // holding a reference.
  history::HistoryBackend* history_backend_;
  base::MessageLoop* backend_loop_;

  content::NotificationRegistrar notification_registrar_;

  scoped_ptr<content::NotificationService> notification_service_;

  // The set of pending changes that will be written out on the next
  // CommitChangesFromSyncModel() call.
  history::URLRows pending_new_urls_;
  history::URLRows pending_updated_urls_;
  std::vector<GURL> pending_deleted_urls_;
  TypedUrlModelAssociator::TypedUrlVisitVector pending_new_visits_;
  history::VisitVector pending_deleted_visits_;

  bool disconnected_;
  base::Lock disconnect_lock_;

  DISALLOW_COPY_AND_ASSIGN(TypedUrlChangeProcessor);
};

}  // namespace browser_sync

#endif  // CHROME_BROWSER_SYNC_GLUE_TYPED_URL_CHANGE_PROCESSOR_H_