1 // Copyright 2016 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 COMPONENTS_SYNC_ENGINE_IMPL_LOOPBACK_SERVER_LOOPBACK_SERVER_H_ 6 #define COMPONENTS_SYNC_ENGINE_IMPL_LOOPBACK_SERVER_LOOPBACK_SERVER_H_ 7 8 #include <stdint.h> 9 10 #include <map> 11 #include <memory> 12 #include <string> 13 #include <vector> 14 15 #include "base/callback.h" 16 #include "base/files/file_path.h" 17 #include "base/files/important_file_writer.h" 18 #include "base/optional.h" 19 #include "base/sequence_checker.h" 20 #include "base/values.h" 21 #include "components/sync/base/model_type.h" 22 #include "components/sync/engine_impl/loopback_server/loopback_server_entity.h" 23 #include "components/sync/protocol/loopback_server.pb.h" 24 #include "components/sync/protocol/sync.pb.h" 25 #include "net/http/http_status_code.h" 26 27 namespace fake_server { 28 class FakeServer; 29 } 30 31 namespace syncer { 32 33 // A loopback version of the Sync server used for local profile serialization. 34 class LoopbackServer : public base::ImportantFileWriter::DataSerializer { 35 public: 36 class ObserverForTests { 37 public: ~ObserverForTests()38 virtual ~ObserverForTests() {} 39 40 // Called after the server has processed a successful commit. The types 41 // updated as part of the commit are passed in |committed_model_types|. 42 virtual void OnCommit(const std::string& committer_invalidator_client_id, 43 syncer::ModelTypeSet committed_model_types) = 0; 44 45 // Called when a page URL is committed via SESSIONS and the user has 46 // enabled "history sync" in the settings UI (which is detected by verifying 47 // if TYPED_URLS is an enabled type, as part of the commit request). 48 virtual void OnHistoryCommit(const std::string& url) = 0; 49 }; 50 51 explicit LoopbackServer(const base::FilePath& persistent_file); 52 ~LoopbackServer() override; 53 54 // Handles a /command POST (with the given |message|) to the server. 55 // |response| must not be null. 56 net::HttpStatusCode HandleCommand( 57 const sync_pb::ClientToServerMessage& message, 58 sync_pb::ClientToServerResponse* response); 59 60 // Enables strong consistency model (i.e. server detects conflicts). 61 void EnableStrongConsistencyWithConflictDetectionModel(); 62 63 // Sets a maximum batch size for GetUpdates requests. SetMaxGetUpdatesBatchSize(int batch_size)64 void SetMaxGetUpdatesBatchSize(int batch_size) { 65 max_get_updates_batch_size_ = batch_size; 66 } 67 SetBagOfChipsForTesting(const sync_pb::ChipBag & bag_of_chips)68 void SetBagOfChipsForTesting(const sync_pb::ChipBag& bag_of_chips) { 69 bag_of_chips_ = bag_of_chips; 70 } 71 TriggerMigrationForTesting(ModelTypeSet model_types)72 void TriggerMigrationForTesting(ModelTypeSet model_types) { 73 for (const ModelType type : model_types) { 74 ++migration_versions_[type]; 75 } 76 } 77 GetKeystoreKeysForTesting()78 const std::vector<std::vector<uint8_t>>& GetKeystoreKeysForTesting() const { 79 return keystore_keys_; 80 } 81 82 void AddNewKeystoreKeyForTesting(); 83 SetThrottledTypesForTesting(ModelTypeSet model_types)84 void SetThrottledTypesForTesting(ModelTypeSet model_types) { 85 throttled_types_ = model_types; 86 } 87 88 private: 89 // Allow the FakeServer decorator to inspect the internals of this class. 90 friend class fake_server::FakeServer; 91 92 using EntityMap = 93 std::map<std::string, std::unique_ptr<LoopbackServerEntity>>; 94 95 using ResponseTypeProvider = 96 base::RepeatingCallback<sync_pb::CommitResponse::ResponseType( 97 const LoopbackServerEntity& entity)>; 98 99 // ImportantFileWriter::DataSerializer: 100 bool SerializeData(std::string* data) override; 101 102 // Gets LoopbackServer ready for syncing. 103 void Init(); 104 105 // Processes a GetUpdates call. 106 bool HandleGetUpdatesRequest(const sync_pb::GetUpdatesMessage& get_updates, 107 const std::string& store_birthday, 108 const std::string& invalidator_client_id, 109 sync_pb::GetUpdatesResponse* response, 110 std::vector<ModelType>* datatypes_to_migrate); 111 112 // Processes a Commit call. 113 bool HandleCommitRequest(const sync_pb::CommitMessage& message, 114 const std::string& invalidator_client_id, 115 sync_pb::CommitResponse* response, 116 ModelTypeSet* throttled_datatypes_in_request); 117 118 void ClearServerData(); 119 120 // Creates and saves a permanent folder for Bookmarks (e.g., Bookmark Bar). 121 bool CreatePermanentBookmarkFolder(const std::string& server_tag, 122 const std::string& name); 123 124 // Inserts the default permanent items in |entities_|. 125 bool CreateDefaultPermanentItems(); 126 127 // Returns generated key which may contain any bytes (not necessarily UTF-8). 128 std::vector<uint8_t> GenerateNewKeystoreKey() const; 129 130 // Saves a |entity| to |entities_|. 131 void SaveEntity(std::unique_ptr<LoopbackServerEntity> entity); 132 133 // Commits a client-side SyncEntity to the server as a LoopbackServerEntity. 134 // The client that sent the commit is identified via |client_guid|. The 135 // parent ID string present in |client_entity| should be ignored in favor 136 // of |parent_id|. If the commit is successful, the entity's server ID string 137 // is returned and a new LoopbackServerEntity is saved in |entities_|. 138 std::string CommitEntity( 139 const sync_pb::SyncEntity& client_entity, 140 sync_pb::CommitResponse_EntryResponse* entry_response, 141 const std::string& client_guid, 142 const std::string& parent_id); 143 144 // Populates |entry_response| based on the stored entity identified by 145 // |entity_id|. It is assumed that the entity identified by |entity_id| has 146 // already been stored using SaveEntity. 147 void BuildEntryResponseForSuccessfulCommit( 148 const std::string& entity_id, 149 sync_pb::CommitResponse_EntryResponse* entry_response); 150 151 // Determines whether the SyncEntity with id_string |id| is a child of an 152 // entity with id_string |potential_parent_id|. 153 bool IsChild(const std::string& id, const std::string& potential_parent_id); 154 155 // Creates and saves tombstones for all children of the entity with the given 156 // |parent_id|. A tombstone is not created for the entity itself. 157 void DeleteChildren(const std::string& parent_id); 158 159 // Updates the |entity| to a new version and increments the version counter 160 // that the server uses to assign versions. 161 void UpdateEntityVersion(LoopbackServerEntity* entity); 162 163 // Returns the store birthday. 164 std::string GetStoreBirthday() const; 165 166 // Returns all entities stored by the server of the given |model_type|. 167 // Permanent entities are excluded. This method is only used in tests. 168 std::vector<sync_pb::SyncEntity> GetSyncEntitiesByModelType( 169 syncer::ModelType model_type); 170 171 // Returns a list of permanent entities of the given |model_type|. This method 172 // is only used in tests. 173 std::vector<sync_pb::SyncEntity> GetPermanentSyncEntitiesByModelType( 174 syncer::ModelType model_type); 175 176 // Creates a DicionaryValue representation of all entities present in the 177 // server. The dictionary keys are the strings generated by ModelTypeToString 178 // and the values are ListValues containing StringValue versions of entity 179 // names. Permanent entities are excluded. Used by test to verify the contents 180 // of the server state. 181 std::unique_ptr<base::DictionaryValue> GetEntitiesAsDictionaryValue(); 182 183 // Modifies the entity on the server with the given |id|. The entity's 184 // EntitySpecifics are replaced with |updated_specifics| and its version is 185 // updated to n+1. If the given |id| does not exist or the ModelType of 186 // |updated_specifics| does not match the entity, false is returned. 187 // Otherwise, true is returned to represent a successful modification. 188 // 189 // This method sometimes updates entity data beyond EntitySpecifics. For 190 // example, in the case of a bookmark, changing the BookmarkSpecifics title 191 // field will modify the top-level entity's name field. 192 // This method is only used in tests. 193 bool ModifyEntitySpecifics(const std::string& id, 194 const sync_pb::EntitySpecifics& updated_specifics); 195 196 // This method is only used in tests. 197 bool ModifyBookmarkEntity(const std::string& id, 198 const std::string& parent_id, 199 const sync_pb::EntitySpecifics& updated_specifics); 200 201 // Use this callback to generate response types for entities. They will still 202 // be "committed" and stored as normal, this only affects the response type 203 // the client sees. This allows tests to still inspect what the client has 204 // done, although not as useful of a mechanism for multi client tests. Care 205 // should be taken when failing responses, as the client will go into 206 // exponential backoff, which can cause tests to be slow or time out. 207 // This method is only used in tests. 208 void OverrideResponseType(ResponseTypeProvider response_type_override); 209 210 // Serializes the server state to |proto|. 211 void SerializeState(sync_pb::LoopbackServerProto* proto) const; 212 213 // Populates the server state from |proto|. Returns true iff successful. 214 bool DeSerializeState(const sync_pb::LoopbackServerProto& proto); 215 216 // Schedules committing state to disk at some later time. Repeat calls are 217 // batched together. Outstanding scheduled writes are committed at shutdown. 218 // Returns true on success. 219 bool ScheduleSaveStateToFile(); 220 221 // Loads all entities and server state from a protobuf file. Returns true on 222 // success. 223 bool LoadStateFromFile(); 224 set_observer_for_tests(ObserverForTests * observer)225 void set_observer_for_tests(ObserverForTests* observer) { 226 observer_for_tests_ = observer; 227 } 228 229 bool strong_consistency_model_enabled_; 230 231 // This is the last version number assigned to an entity. The next entity will 232 // have a version number of version_ + 1. 233 int64_t version_; 234 235 int64_t store_birthday_; 236 237 ModelTypeSet throttled_types_; 238 239 base::Optional<sync_pb::ChipBag> bag_of_chips_; 240 241 std::map<ModelType, int> migration_versions_; 242 243 int max_get_updates_batch_size_ = 1000000; 244 245 EntityMap entities_; 246 std::vector<std::vector<uint8_t>> keystore_keys_; 247 248 // The file used to store the local sync data. 249 base::FilePath persistent_file_; 250 251 // Used to limit the rate of file rewrites due to updates. 252 base::ImportantFileWriter writer_; 253 254 // Used to verify that LoopbackServer is only used from one sequence. 255 SEQUENCE_CHECKER(sequence_checker_); 256 257 // Used to observe the completion of commit messages for the sake of testing. 258 ObserverForTests* observer_for_tests_; 259 260 // Response type override callback used in tests. 261 ResponseTypeProvider response_type_override_; 262 }; 263 264 } // namespace syncer 265 266 #endif // COMPONENTS_SYNC_ENGINE_IMPL_LOOPBACK_SERVER_LOOPBACK_SERVER_H_ 267