verify_updates_command.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2010 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
6#include "chrome/browser/sync/engine/verify_updates_command.h"
7
8#include "chrome/browser/sync/engine/syncer.h"
9#include "chrome/browser/sync/engine/syncer_proto_util.h"
10#include "chrome/browser/sync/engine/syncer_types.h"
11#include "chrome/browser/sync/engine/syncer_util.h"
12#include "chrome/browser/sync/engine/syncproto.h"
13#include "chrome/browser/sync/protocol/bookmark_specifics.pb.h"
14#include "chrome/browser/sync/syncable/directory_manager.h"
15#include "chrome/browser/sync/syncable/syncable.h"
16
17namespace browser_sync {
18
19using syncable::ScopedDirLookup;
20using syncable::SyncName;
21using syncable::WriteTransaction;
22
23using syncable::GET_BY_ID;
24using syncable::SYNCER;
25
26VerifyUpdatesCommand::VerifyUpdatesCommand() {}
27VerifyUpdatesCommand::~VerifyUpdatesCommand() {}
28
29void VerifyUpdatesCommand::ModelChangingExecuteImpl(
30    sessions::SyncSession* session) {
31  VLOG(1) << "Beginning Update Verification";
32  ScopedDirLookup dir(session->context()->directory_manager(),
33                      session->context()->account_name());
34  if (!dir.good()) {
35    LOG(ERROR) << "Scoped dir lookup failed!";
36    return;
37  }
38  WriteTransaction trans(dir, SYNCER, __FILE__, __LINE__);
39  sessions::StatusController* status = session->status_controller();
40  const GetUpdatesResponse& updates = status->updates_response().get_updates();
41  int update_count = updates.entries().size();
42
43  VLOG(1) << update_count << " entries to verify";
44  for (int i = 0; i < update_count; i++) {
45    const SyncEntity& update =
46        *reinterpret_cast<const SyncEntity *>(&(updates.entries(i)));
47    ModelSafeGroup g = GetGroupForModelType(update.GetModelType(),
48                                            session->routing_info());
49    if (g != status->group_restriction())
50      continue;
51
52    VerifyUpdateResult result = VerifyUpdate(&trans, update,
53                                             session->routing_info());
54    status->mutable_update_progress()->AddVerifyResult(result.value, update);
55  }
56}
57
58namespace {
59// In the event that IDs match, but tags differ AttemptReuniteClient tag
60// will have refused to unify the update.
61// We should not attempt to apply it at all since it violates consistency
62// rules.
63VerifyResult VerifyTagConsistency(const SyncEntity& entry,
64                                  const syncable::MutableEntry& same_id) {
65  if (entry.has_client_defined_unique_tag() &&
66      entry.client_defined_unique_tag() !=
67          same_id.Get(syncable::UNIQUE_CLIENT_TAG)) {
68    return VERIFY_FAIL;
69  }
70  return VERIFY_UNDECIDED;
71}
72}  // namespace
73
74VerifyUpdatesCommand::VerifyUpdateResult VerifyUpdatesCommand::VerifyUpdate(
75    syncable::WriteTransaction* trans, const SyncEntity& entry,
76    const ModelSafeRoutingInfo& routes) {
77  syncable::Id id = entry.id();
78  VerifyUpdateResult result = {VERIFY_FAIL, GROUP_PASSIVE};
79
80  const bool deleted = entry.has_deleted() && entry.deleted();
81  const bool is_directory = entry.IsFolder();
82  const syncable::ModelType model_type = entry.GetModelType();
83
84  if (!id.ServerKnows()) {
85    LOG(ERROR) << "Illegal negative id in received updates";
86    return result;
87  }
88  {
89    const std::string name = SyncerProtoUtil::NameFromSyncEntity(entry);
90    if (name.empty() && !deleted) {
91      LOG(ERROR) << "Zero length name in non-deleted update";
92      return result;
93    }
94  }
95
96  syncable::MutableEntry same_id(trans, GET_BY_ID, id);
97  result.value = SyncerUtil::VerifyNewEntry(entry, &same_id, deleted);
98
99  syncable::ModelType placement_type = !deleted ? entry.GetModelType()
100      : same_id.good() ? same_id.GetModelType() : syncable::UNSPECIFIED;
101  result.placement = GetGroupForModelType(placement_type, routes);
102
103  if (VERIFY_UNDECIDED == result.value) {
104    result.value = VerifyTagConsistency(entry, same_id);
105  }
106
107  if (VERIFY_UNDECIDED == result.value) {
108    if (deleted)
109      result.value = VERIFY_SUCCESS;
110  }
111
112  // If we have an existing entry, we check here for updates that break
113  // consistency rules.
114  if (VERIFY_UNDECIDED == result.value) {
115    result.value = SyncerUtil::VerifyUpdateConsistency(trans, entry, &same_id,
116        deleted, is_directory, model_type);
117  }
118
119  if (VERIFY_UNDECIDED == result.value)
120    result.value = VERIFY_SUCCESS;  // No news is good news.
121
122  return result;  // This might be VERIFY_SUCCESS as well
123}
124
125}  // namespace browser_sync
126