1 // Copyright 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 SYNC_INTERNAL_API_PUBLIC_BASE_NODE_H_ 6 #define SYNC_INTERNAL_API_PUBLIC_BASE_NODE_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/gtest_prod_util.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/time/time.h" 15 #include "sync/base/sync_export.h" 16 #include "sync/internal_api/public/base/model_type.h" 17 #include "sync/protocol/sync.pb.h" 18 #include "url/gurl.h" 19 20 // Forward declarations of internal class types so that sync API objects 21 // may have opaque pointers to these types. 22 namespace base { 23 class DictionaryValue; 24 } 25 26 namespace sync_pb { 27 class AppSpecifics; 28 class AutofillSpecifics; 29 class AutofillProfileSpecifics; 30 class BookmarkSpecifics; 31 class EntitySpecifics; 32 class ExtensionSpecifics; 33 class SessionSpecifics; 34 class NigoriSpecifics; 35 class PreferenceSpecifics; 36 class PasswordSpecificsData; 37 class ThemeSpecifics; 38 class TypedUrlSpecifics; 39 } 40 41 namespace syncer { 42 43 class BaseTransaction; 44 45 namespace syncable { 46 class BaseTransaction; 47 class Entry; 48 } 49 50 // A valid BaseNode will never have an ID of zero. 51 static const int64 kInvalidId = 0; 52 53 // BaseNode wraps syncable::Entry, and corresponds to a single object's state. 54 // This, like syncable::Entry, is intended for use on the stack. A valid 55 // transaction is necessary to create a BaseNode or any of its children. 56 // Unlike syncable::Entry, a sync API BaseNode is identified primarily by its 57 // int64 metahandle, which we call an ID here. 58 class SYNC_EXPORT BaseNode { 59 public: 60 // Enumerates the possible outcomes of trying to initialize a sync node. 61 enum InitByLookupResult { 62 INIT_OK, 63 // Could not find an entry matching the lookup criteria. 64 INIT_FAILED_ENTRY_NOT_GOOD, 65 // Found an entry, but it is already deleted. 66 INIT_FAILED_ENTRY_IS_DEL, 67 // Found an entry, but was unable to decrypt. 68 INIT_FAILED_DECRYPT_IF_NECESSARY, 69 // A precondition was not met for calling init, such as legal input 70 // arguments. 71 INIT_FAILED_PRECONDITION, 72 }; 73 74 // All subclasses of BaseNode must provide a way to initialize themselves by 75 // doing an ID lookup. Returns false on failure. An invalid or deleted 76 // ID will result in failure. 77 virtual InitByLookupResult InitByIdLookup(int64 id) = 0; 78 79 // All subclasses of BaseNode must also provide a way to initialize themselves 80 // by doing a client tag lookup. Returns false on failure. A deleted node 81 // will return FALSE. 82 virtual InitByLookupResult InitByClientTagLookup( 83 ModelType model_type, 84 const std::string& tag) = 0; 85 86 // Each object is identified by a 64-bit id (internally, the syncable 87 // metahandle). These ids are strictly local handles. They will persist 88 // on this client, but the same object on a different client may have a 89 // different ID value. 90 virtual int64 GetId() const; 91 92 // Returns the modification time of the object. 93 base::Time GetModificationTime() const; 94 95 // Nodes are hierarchically arranged into a single-rooted tree. 96 // InitByRootLookup on ReadNode allows access to the root. GetParentId is 97 // how you find a node's parent. 98 int64 GetParentId() const; 99 100 // Nodes are either folders or not. This corresponds to the IS_DIR property 101 // of syncable::Entry. 102 bool GetIsFolder() const; 103 104 // Returns the title of the object. 105 // Uniqueness of the title is not enforced on siblings -- it is not an error 106 // for two children to share a title. 107 std::string GetTitle() const; 108 109 // Returns the model type of this object. The model type is set at node 110 // creation time and is expected never to change. 111 ModelType GetModelType() const; 112 113 // Getter specific to the BOOKMARK datatype. Returns protobuf 114 // data. Can only be called if GetModelType() == BOOKMARK. 115 const sync_pb::BookmarkSpecifics& GetBookmarkSpecifics() const; 116 117 // Getter specific to the APPS datatype. Returns protobuf 118 // data. Can only be called if GetModelType() == APPS. 119 const sync_pb::AppSpecifics& GetAppSpecifics() const; 120 121 // Getter specific to the AUTOFILL datatype. Returns protobuf 122 // data. Can only be called if GetModelType() == AUTOFILL. 123 const sync_pb::AutofillSpecifics& GetAutofillSpecifics() const; 124 125 virtual const sync_pb::AutofillProfileSpecifics& 126 GetAutofillProfileSpecifics() const; 127 128 // Getter specific to the NIGORI datatype. Returns protobuf 129 // data. Can only be called if GetModelType() == NIGORI. 130 const sync_pb::NigoriSpecifics& GetNigoriSpecifics() const; 131 132 // Getter specific to the PASSWORD datatype. Returns protobuf 133 // data. Can only be called if GetModelType() == PASSWORD. 134 const sync_pb::PasswordSpecificsData& GetPasswordSpecifics() const; 135 136 // Getter specific to the PREFERENCE datatype. Returns protobuf 137 // data. Can only be called if GetModelType() == PREFERENCE. 138 const sync_pb::PreferenceSpecifics& GetPreferenceSpecifics() const; 139 140 // Getter specific to the THEME datatype. Returns protobuf 141 // data. Can only be called if GetModelType() == THEME. 142 const sync_pb::ThemeSpecifics& GetThemeSpecifics() const; 143 144 // Getter specific to the TYPED_URLS datatype. Returns protobuf 145 // data. Can only be called if GetModelType() == TYPED_URLS. 146 const sync_pb::TypedUrlSpecifics& GetTypedUrlSpecifics() const; 147 148 // Getter specific to the EXTENSIONS datatype. Returns protobuf 149 // data. Can only be called if GetModelType() == EXTENSIONS. 150 const sync_pb::ExtensionSpecifics& GetExtensionSpecifics() const; 151 152 // Getter specific to the SESSIONS datatype. Returns protobuf 153 // data. Can only be called if GetModelType() == SESSIONS. 154 const sync_pb::SessionSpecifics& GetSessionSpecifics() const; 155 156 // Getter specific to the MANAGED_USER_SETTINGS datatype. Returns protobuf 157 // data. Can only be called if GetModelType() == MANAGED_USER_SETTINGS. 158 const sync_pb::ManagedUserSettingSpecifics& 159 GetManagedUserSettingSpecifics() const; 160 161 // Getter specific to the MANAGED_USERS datatype. Returns protobuf data. 162 // Can only be called if GetModelType() == MANAGED_USERS. 163 const sync_pb::ManagedUserSpecifics& GetManagedUserSpecifics() const; 164 165 // Getter specific to the DEVICE_INFO datatype. Returns protobuf 166 // data. Can only be called if GetModelType() == DEVICE_INFO. 167 const sync_pb::DeviceInfoSpecifics& GetDeviceInfoSpecifics() const; 168 169 // Getter specific to the EXPERIMENTS datatype. Returns protobuf 170 // data. Can only be called if GetModelType() == EXPERIMENTS. 171 const sync_pb::ExperimentsSpecifics& GetExperimentsSpecifics() const; 172 173 // Getter specific to the PRIORITY_PREFERENCE datatype. Returns protobuf 174 // data. Can only be called if GetModelType() == PRIORITY_PREFERENCE. 175 const sync_pb::PriorityPreferenceSpecifics& 176 GetPriorityPreferenceSpecifics() const; 177 178 const sync_pb::EntitySpecifics& GetEntitySpecifics() const; 179 180 // Returns the local external ID associated with the node. 181 int64 GetExternalId() const; 182 183 // Returns true iff this node has children. 184 bool HasChildren() const; 185 186 // Return the ID of the node immediately before this in the sibling order. 187 // For the first node in the ordering, return 0. 188 int64 GetPredecessorId() const; 189 190 // Return the ID of the node immediately after this in the sibling order. 191 // For the last node in the ordering, return 0. 192 int64 GetSuccessorId() const; 193 194 // Return the ID of the first child of this node. If this node has no 195 // children, return 0. 196 int64 GetFirstChildId() const; 197 198 // Returns the IDs of the children of this node. 199 // If this type supports user-defined positions the returned IDs will be in 200 // the correct order. 201 void GetChildIds(std::vector<int64>* result) const; 202 203 // Returns the total number of nodes including and beneath this node. 204 // Recursively iterates through all children. 205 int GetTotalNodeCount() const; 206 207 // Returns this item's position within its parent. 208 // Do not call this function on items that do not support positioning 209 // (ie. non-bookmarks). 210 int GetPositionIndex() const; 211 212 // These virtual accessors provide access to data members of derived classes. 213 virtual const syncable::Entry* GetEntry() const = 0; 214 virtual const BaseTransaction* GetTransaction() const = 0; 215 216 // Dumps a summary of node info into a DictionaryValue and returns it. 217 // Transfers ownership of the DictionaryValue to the caller. 218 base::DictionaryValue* GetSummaryAsValue() const; 219 220 // Dumps all node details into a DictionaryValue and returns it. 221 // Transfers ownership of the DictionaryValue to the caller. 222 base::DictionaryValue* GetDetailsAsValue() const; 223 224 protected: 225 BaseNode(); 226 virtual ~BaseNode(); 227 228 // Determines whether part of the entry is encrypted, and if so attempts to 229 // decrypt it. Unless decryption is necessary and fails, this will always 230 // return |true|. If the contents are encrypted, the decrypted data will be 231 // stored in |unencrypted_data_|. 232 // This method is invoked once when the BaseNode is initialized. 233 bool DecryptIfNecessary(); 234 235 // Returns the unencrypted specifics associated with |entry|. If |entry| was 236 // not encrypted, it directly returns |entry|'s EntitySpecifics. Otherwise, 237 // returns |unencrypted_data_|. 238 const sync_pb::EntitySpecifics& GetUnencryptedSpecifics( 239 const syncable::Entry* entry) const; 240 241 // Copy |specifics| into |unencrypted_data_|. 242 void SetUnencryptedSpecifics(const sync_pb::EntitySpecifics& specifics); 243 244 private: 245 // Have to friend the test class as well to allow member functions to access 246 // protected/private BaseNode methods. 247 friend class SyncManagerTest; 248 FRIEND_TEST_ALL_PREFIXES(SyncApiTest, GenerateSyncableHash); 249 FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdateEntryWithEncryption); 250 FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, 251 UpdatePasswordSetEntitySpecificsNoChange); 252 FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdatePasswordSetPasswordSpecifics); 253 FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdatePasswordNewPassphrase); 254 FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdatePasswordReencryptEverything); 255 FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetBookmarkTitle); 256 FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetBookmarkTitleWithEncryption); 257 FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetNonBookmarkTitle); 258 FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetNonBookmarkTitleWithEncryption); 259 FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetPreviouslyEncryptedSpecifics); 260 FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, IncrementTransactionVersion); 261 262 void* operator new(size_t size); // Node is meant for stack use only. 263 264 // A holder for the unencrypted data stored in an encrypted node. 265 sync_pb::EntitySpecifics unencrypted_data_; 266 267 // Same as |unencrypted_data_|, but for legacy password encryption. 268 scoped_ptr<sync_pb::PasswordSpecificsData> password_data_; 269 270 DISALLOW_COPY_AND_ASSIGN(BaseNode); 271 }; 272 273 } // namespace syncer 274 275 #endif // SYNC_INTERNAL_API_PUBLIC_BASE_NODE_H_ 276