Home | History | Annotate | Download | only in public
      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