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