• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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