Home | History | Annotate | Download | only in syncable
      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 #include "sync/syncable/syncable_util.h"
      6 
      7 #include "base/base64.h"
      8 #include "base/location.h"
      9 #include "base/logging.h"
     10 #include "base/sha1.h"
     11 #include "sync/syncable/directory.h"
     12 #include "sync/syncable/entry.h"
     13 #include "sync/syncable/mutable_entry.h"
     14 #include "sync/syncable/syncable_id.h"
     15 #include "sync/syncable/syncable_write_transaction.h"
     16 
     17 namespace syncer {
     18 namespace syncable {
     19 
     20 // Returns the number of unsynced entries.
     21 int GetUnsyncedEntries(BaseTransaction* trans,
     22                        std::vector<int64> *handles) {
     23   trans->directory()->GetUnsyncedMetaHandles(trans, handles);
     24   DVLOG_IF(1, !handles->empty()) << "Have " << handles->size()
     25                                  << " unsynced items.";
     26   return handles->size();
     27 }
     28 
     29 bool IsLegalNewParent(BaseTransaction* trans, const Id& entry_id,
     30                       const Id& new_parent_id) {
     31   if (entry_id.IsRoot())
     32     return false;
     33   // we have to ensure that the entry is not an ancestor of the new parent.
     34   Id ancestor_id = new_parent_id;
     35   while (!ancestor_id.IsRoot()) {
     36     if (entry_id == ancestor_id)
     37       return false;
     38     Entry new_parent(trans, GET_BY_ID, ancestor_id);
     39     if (!SyncAssert(new_parent.good(),
     40                     FROM_HERE,
     41                     "Invalid new parent",
     42                     trans))
     43       return false;
     44     ancestor_id = new_parent.Get(PARENT_ID);
     45   }
     46   return true;
     47 }
     48 
     49 void ChangeEntryIDAndUpdateChildren(
     50     WriteTransaction* trans,
     51     MutableEntry* entry,
     52     const Id& new_id) {
     53   Id old_id = entry->Get(ID);
     54   if (!entry->Put(ID, new_id)) {
     55     Entry old_entry(trans, GET_BY_ID, new_id);
     56     CHECK(old_entry.good());
     57     LOG(FATAL) << "Attempt to change ID to " << new_id
     58                << " conflicts with existing entry.\n\n"
     59                << *entry << "\n\n" << old_entry;
     60   }
     61   if (entry->Get(IS_DIR)) {
     62     // Get all child entries of the old id.
     63     Directory::Metahandles children;
     64     trans->directory()->GetChildHandlesById(trans, old_id, &children);
     65     Directory::Metahandles::iterator i = children.begin();
     66     while (i != children.end()) {
     67       MutableEntry child_entry(trans, GET_BY_HANDLE, *i++);
     68       CHECK(child_entry.good());
     69       // Use the unchecked setter here to avoid touching the child's
     70       // UNIQUE_POSITION field.  In this case, UNIQUE_POSITION among the
     71       // children will be valid after the loop, since we update all the children
     72       // at once.
     73       child_entry.PutParentIdPropertyOnly(new_id);
     74     }
     75   }
     76 }
     77 
     78 // Function to handle runtime failures on syncable code. Rather than crashing,
     79 // if the |condition| is false the following will happen:
     80 // 1. Sets unrecoverable error on transaction.
     81 // 2. Returns false.
     82 bool SyncAssert(bool condition,
     83                 const tracked_objects::Location& location,
     84                 const char* msg,
     85                 BaseTransaction* trans) {
     86   if (!condition) {
     87     trans->OnUnrecoverableError(location, msg);
     88     return false;
     89   }
     90   return true;
     91 }
     92 
     93 std::string GenerateSyncableHash(
     94     ModelType model_type, const std::string& client_tag) {
     95   // Blank PB with just the field in it has termination symbol,
     96   // handy for delimiter.
     97   sync_pb::EntitySpecifics serialized_type;
     98   AddDefaultFieldValue(model_type, &serialized_type);
     99   std::string hash_input;
    100   serialized_type.AppendToString(&hash_input);
    101   hash_input.append(client_tag);
    102 
    103   std::string encode_output;
    104   CHECK(base::Base64Encode(base::SHA1HashString(hash_input), &encode_output));
    105   return encode_output;
    106 }
    107 
    108 std::string GenerateSyncableBookmarkHash(
    109     const std::string originator_cache_guid,
    110     const std::string originator_client_item_id) {
    111   return syncable::GenerateSyncableHash(
    112       BOOKMARKS, originator_cache_guid + originator_client_item_id);
    113 }
    114 
    115 }  // namespace syncable
    116 }  // namespace syncer
    117