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 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
|
// Copyright 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 COMPONENTS_SYNC_SYNCABLE_BASE_NODE_H_
#define COMPONENTS_SYNC_SYNCABLE_BASE_NODE_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "components/sync/base/model_type.h"
#include "components/sync/model/attachments/attachment.h"
#include "components/sync/protocol/sync.pb.h"
#include "url/gurl.h"
// Forward declarations of internal class types so that sync API objects
// may have opaque pointers to these types.
namespace base {
class DictionaryValue;
}
namespace sync_pb {
class BookmarkSpecifics;
class EntitySpecifics;
class NigoriSpecifics;
class PasswordSpecificsData;
class TypedUrlSpecifics;
} // namespace sync_pb
namespace syncer {
class BaseTransaction;
namespace syncable {
class BaseTransaction;
class Entry;
class Id;
}
// A valid BaseNode will never have an ID of zero.
static const int64_t kInvalidId = 0;
// BaseNode wraps syncable::Entry, and corresponds to a single object's state.
// This, like syncable::Entry, is intended for use on the stack. A valid
// transaction is necessary to create a BaseNode or any of its children.
// Unlike syncable::Entry, a sync API BaseNode is identified primarily by its
// int64_t metahandle, which we call an ID here.
class BaseNode {
public:
// Enumerates the possible outcomes of trying to initialize a sync node.
enum InitByLookupResult {
INIT_OK,
// Could not find an entry matching the lookup criteria.
INIT_FAILED_ENTRY_NOT_GOOD,
// Found an entry, but it is already deleted.
INIT_FAILED_ENTRY_IS_DEL,
// Found an entry, but was unable to decrypt.
INIT_FAILED_DECRYPT_IF_NECESSARY,
// A precondition was not met for calling init, such as legal input
// arguments.
INIT_FAILED_PRECONDITION,
};
// All subclasses of BaseNode must provide a way to initialize themselves by
// doing an ID lookup. Returns false on failure. An invalid or deleted
// ID will result in failure.
virtual InitByLookupResult InitByIdLookup(int64_t id) = 0;
// All subclasses of BaseNode must also provide a way to initialize themselves
// by doing a client tag lookup. Returns false on failure. A deleted node
// will return FALSE.
virtual InitByLookupResult InitByClientTagLookup(ModelType model_type,
const std::string& tag) = 0;
// Each object is identified by a 64-bit id (internally, the syncable
// metahandle). These ids are strictly local handles. They will persist
// on this client, but the same object on a different client may have a
// different ID value.
virtual int64_t GetId() const;
// Returns the modification time of the object.
base::Time GetModificationTime() const;
// Nodes are hierarchically arranged into a single-rooted tree.
// InitByRootLookup on ReadNode allows access to the root. GetParentId is
// how you find a node's parent.
int64_t GetParentId() const;
// Nodes are either folders or not. This corresponds to the IS_DIR property
// of syncable::Entry.
bool GetIsFolder() const;
// Specifies whether node is a permanent folder. This is true when
// UNIQUE_SERVER_TAG property of syncable::Entry is non-empty.
bool GetIsPermanentFolder() const;
// Returns the title of the object.
// Uniqueness of the title is not enforced on siblings -- it is not an error
// for two children to share a title.
std::string GetTitle() const;
// Returns the model type of this object. The model type is set at node
// creation time and is expected never to change.
ModelType GetModelType() const;
// Getter specific to the BOOKMARK datatype. Returns protobuf
// data. Can only be called if GetModelType() == BOOKMARK.
const sync_pb::BookmarkSpecifics& GetBookmarkSpecifics() const;
// Getter specific to the NIGORI datatype. Returns protobuf
// data. Can only be called if GetModelType() == NIGORI.
const sync_pb::NigoriSpecifics& GetNigoriSpecifics() const;
// Getter specific to the PASSWORD datatype. Returns protobuf
// data. Can only be called if GetModelType() == PASSWORD.
const sync_pb::PasswordSpecificsData& GetPasswordSpecifics() const;
// Getter specific to the TYPED_URLS datatype. Returns protobuf
// data. Can only be called if GetModelType() == TYPED_URLS.
const sync_pb::TypedUrlSpecifics& GetTypedUrlSpecifics() const;
// Getter specific to the EXPERIMENTS datatype. Returns protobuf
// data. Can only be called if GetModelType() == EXPERIMENTS.
const sync_pb::ExperimentsSpecifics& GetExperimentsSpecifics() const;
const sync_pb::EntitySpecifics& GetEntitySpecifics() const;
// Returns the local external ID associated with the node.
int64_t GetExternalId() const;
// Returns the internal syncable ID associated with the node.
const syncable::Id& GetSyncId() const;
// Returns true iff this node has children.
bool HasChildren() const;
// Return the ID of the node immediately before this in the sibling order.
// For the first node in the ordering, return 0.
int64_t GetPredecessorId() const;
// Return the ID of the node immediately after this in the sibling order.
// For the last node in the ordering, return 0.
int64_t GetSuccessorId() const;
// Return the ID of the first child of this node. If this node has no
// children, return 0.
int64_t GetFirstChildId() const;
// Returns the IDs of the children of this node.
// If this type supports user-defined positions the returned IDs will be in
// the correct order.
void GetChildIds(std::vector<int64_t>* result) const;
// Returns the total number of nodes including and beneath this node.
// Recursively iterates through all children.
int GetTotalNodeCount() const;
// Returns this item's position within its parent.
// Do not call this function on items that do not support positioning
// (ie. non-bookmarks).
int GetPositionIndex() const;
// Returns this item's attachment ids.
const AttachmentIdList GetAttachmentIds() const;
// Returns a base::DictionaryValue serialization of this node.
base::DictionaryValue* ToValue() const;
protected:
BaseNode();
virtual ~BaseNode();
// These virtual accessors provide access to data members of derived classes.
virtual const syncable::Entry* GetEntry() const = 0;
virtual const BaseTransaction* GetTransaction() const = 0;
// Determines whether part of the entry is encrypted, and if so attempts to
// decrypt it. Unless decryption is necessary and fails, this will always
// return |true|. If the contents are encrypted, the decrypted data will be
// stored in |unencrypted_data_|.
// This method is invoked once when the BaseNode is initialized.
bool DecryptIfNecessary();
// Returns the unencrypted specifics associated with |entry|. If |entry| was
// not encrypted, it directly returns |entry|'s EntitySpecifics. Otherwise,
// returns |unencrypted_data_|.
const sync_pb::EntitySpecifics& GetUnencryptedSpecifics(
const syncable::Entry* entry) const;
// Copy |specifics| into |unencrypted_data_|.
void SetUnencryptedSpecifics(const sync_pb::EntitySpecifics& specifics);
private:
// Have to friend the test class as well to allow member functions to access
// protected/private BaseNode methods.
friend class SyncManagerTest;
FRIEND_TEST_ALL_PREFIXES(SyncApiTest, GenerateSyncableHash);
FRIEND_TEST_ALL_PREFIXES(SyncApiTest, WriteEmptyBookmarkTitle);
FRIEND_TEST_ALL_PREFIXES(SyncApiTest, WriteEncryptedTitle);
FRIEND_TEST_ALL_PREFIXES(SyncBackupManagerTest, NormalizeEntry);
FRIEND_TEST_ALL_PREFIXES(SyncBackupManagerTest,
PersistWithSwitchToSyncShutdown);
FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdateEntryWithEncryption);
FRIEND_TEST_ALL_PREFIXES(SyncManagerTest,
UpdatePasswordSetEntitySpecificsNoChange);
FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdatePasswordSetPasswordSpecifics);
FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdatePasswordNewPassphrase);
FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdatePasswordReencryptEverything);
FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetBookmarkTitle);
FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetBookmarkTitleWithEncryption);
FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetNonBookmarkTitle);
FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetNonBookmarkTitleWithEncryption);
FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetPreviouslyEncryptedSpecifics);
FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, IncrementTransactionVersion);
void* operator new(size_t size); // Node is meant for stack use only.
// A holder for the unencrypted data stored in an encrypted node.
sync_pb::EntitySpecifics unencrypted_data_;
// Same as |unencrypted_data_|, but for legacy password encryption.
std::unique_ptr<sync_pb::PasswordSpecificsData> password_data_;
DISALLOW_COPY_AND_ASSIGN(BaseNode);
};
} // namespace syncer
#endif // COMPONENTS_SYNC_SYNCABLE_BASE_NODE_H_
|