summaryrefslogtreecommitdiffstats
path: root/sync/internal_api/public/shared_model_type_processor.h
blob: 782cf8c51a0485c5fd8ada03eaeca16dd5f090b9 (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// Copyright 2014 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 SYNC_INTERNAL_API_PUBLIC_SHARED_MODEL_TYPE_PROCESSOR_H_
#define SYNC_INTERNAL_API_PUBLIC_SHARED_MODEL_TYPE_PROCESSOR_H_

#include <map>
#include <string>

#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "sync/api/data_batch.h"
#include "sync/api/metadata_batch.h"
#include "sync/api/metadata_change_list.h"
#include "sync/api/model_type_change_processor.h"
#include "sync/api/model_type_service.h"
#include "sync/api/sync_error.h"
#include "sync/base/sync_export.h"
#include "sync/internal_api/public/base/model_type.h"
#include "sync/internal_api/public/model_type_processor.h"
#include "sync/internal_api/public/non_blocking_sync_common.h"
#include "sync/protocol/data_type_state.pb.h"
#include "sync/protocol/sync.pb.h"

namespace syncer_v2 {
struct ActivationContext;
class CommitQueue;
class ModelTypeEntity;

// A sync component embedded on the synced type's thread that helps to handle
// communication between sync and model type threads.
class SYNC_EXPORT SharedModelTypeProcessor : public ModelTypeProcessor,
                                             public ModelTypeChangeProcessor,
                                             base::NonThreadSafe {
 public:
  SharedModelTypeProcessor(syncer::ModelType type, ModelTypeService* service);
  ~SharedModelTypeProcessor() override;

  typedef base::Callback<void(syncer::SyncError, scoped_ptr<ActivationContext>)>
      StartCallback;

  // Called by the DataTypeController to gather additional information needed
  // before a CommitQueue object can be created for this model type. Once the
  // metadata has been loaded, the info is collected and given to |callback|.
  // Once called, this can only be called again if sync is disconnected.
  void OnSyncStarting(StartCallback callback);

  // Disconnect this processor from the sync engine. Change metadata will
  // continue being processed and persisted, but no commits can be made until
  // the next time sync is connected.
  void DisconnectSync();

  // Indicates that we no longer want to do any sync-related things for this
  // data type. Severs all ties to the sync thread, deletes all local sync
  // metadata, and then destroys the SharedModelTypeProcessor.
  // TODO(crbug.com/584365): This needs to be called from DataTypeController.
  void Disable();

  // Whether the processor is allowing changes to its model type. If this is
  // false, the service should not allow any changes to its data.
  bool IsAllowingChanges() const;

  // Returns true if the handshake with sync thread is complete.
  bool IsConnected() const;

  // ModelTypeChangeProcessor implementation.
  void Put(const std::string& client_tag,
           scoped_ptr<EntityData> entity_data,
           MetadataChangeList* metadata_change_list) override;
  void Delete(const std::string& client_tag,
              MetadataChangeList* metadata_change_list) override;
  void OnMetadataLoaded(scoped_ptr<MetadataBatch> batch) override;

  // Returns the list of pending updates.
  //
  // This is used as a helper function, but it's public mainly for testing.
  // The current test harness setup doesn't allow us to test the data that the
  // proxy sends to the worker during initialization, so we use this to inspect
  // its state instead.
  UpdateResponseDataList GetPendingUpdates();

  // Returns the long-lived WeakPtr that is intended to be registered with the
  // ProfileSyncService.
  base::WeakPtr<SharedModelTypeProcessor> AsWeakPtrForUI();

  // ModelTypeProcessor implementation.
  void ConnectSync(scoped_ptr<CommitQueue> worker) override;
  void OnCommitCompleted(const sync_pb::DataTypeState& type_state,
                         const CommitResponseDataList& response_list) override;
  void OnUpdateReceived(const sync_pb::DataTypeState& type_state,
                        const UpdateResponseDataList& updates,
                        const UpdateResponseDataList& pending_updates) override;

 private:
  friend class SharedModelTypeProcessorTest;

  using EntityMap = std::map<std::string, scoped_ptr<ModelTypeEntity>>;
  using UpdateMap = std::map<std::string, scoped_ptr<UpdateResponseData>>;

  // Callback for ModelTypeService::GetData(). Used when we need to load data
  // for pending commits during the initialization process.
  void OnDataLoaded(syncer::SyncError error, scoped_ptr<DataBatch> data_batch);

  // Check conditions, and if met inform sync that we are ready to connect.
  void ConnectIfReady();

  // Handle the first update received from the server after being enabled.
  void OnInitialUpdateReceived(const sync_pb::DataTypeState& type_state,
                               const UpdateResponseDataList& updates,
                               const UpdateResponseDataList& pending_updates);

  // Sends all commit requests that are due to be sent to the sync thread.
  void FlushPendingCommitRequests();

  // Computes the client tag hash for the given client |tag|.
  std::string GetHashForTag(const std::string& tag);

  // Gets the entity for the given tag, which must exist.
  ModelTypeEntity* GetEntityForTag(const std::string& tag);

  // Gets the entity for the given tag hash, which must exist.
  ModelTypeEntity* GetEntityForTagHash(const std::string& tag_hash);

  syncer::ModelType type_;
  sync_pb::DataTypeState data_type_state_;

  // Stores the start callback in between OnSyncStarting() and ReadyToConnect().
  StartCallback start_callback_;

  // Indicates whether the metadata has finished loading.
  bool is_metadata_loaded_;

  // Indicates whether data for pending commits has finished loading.
  bool is_pending_commit_data_loaded_;

  // Reference to the CommitQueue.
  //
  // The interface hides the posting of tasks across threads as well as the
  // CommitQueue's implementation.  Both of these features are
  // useful in tests.
  scoped_ptr<CommitQueue> worker_;

  // The set of sync entities known to this object.
  EntityMap entities_;

  // A set of updates that can not be applied at this time.  These are never
  // used by the model.  They are kept here only so we can save and restore
  // them across restarts, and keep them in sync with our progress markers.
  UpdateMap pending_updates_map_;

  // ModelTypeService linked to this processor.
  // The service owns this processor instance so the pointer should never
  // become invalid.
  ModelTypeService* const service_;

  // We use two different WeakPtrFactories because we want the pointers they
  // issue to have different lifetimes.  When asked to disconnect from the sync
  // thread, we want to make sure that no tasks generated as part of the
  // now-obsolete connection to affect us.  But we also want the WeakPtr we
  // sent to the UI thread to remain valid.
  base::WeakPtrFactory<SharedModelTypeProcessor> weak_ptr_factory_;
  base::WeakPtrFactory<SharedModelTypeProcessor> weak_ptr_factory_for_sync_;
};

}  // namespace syncer_v2

#endif  // SYNC_INTERNAL_API_PUBLIC_SHARED_MODEL_TYPE_PROCESSOR_H_