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/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