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