Resize destination bus to the actual number of decoded frames.
[chromium-blink-merge.git] / sync / engine / build_commit_command.cc
blob53c522122b78f400a1f5da3a19d3fa5dbdfd2654
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.
5 #include "sync/engine/build_commit_command.h"
7 #include <limits>
8 #include <set>
9 #include <string>
10 #include <vector>
12 #include "base/strings/string_util.h"
13 #include "sync/engine/syncer_proto_util.h"
14 #include "sync/internal_api/public/base/unique_position.h"
15 #include "sync/protocol/bookmark_specifics.pb.h"
16 #include "sync/protocol/sync.pb.h"
17 #include "sync/sessions/ordered_commit_set.h"
18 #include "sync/sessions/sync_session.h"
19 #include "sync/syncable/directory.h"
20 #include "sync/syncable/entry.h"
21 #include "sync/syncable/syncable_base_transaction.h"
22 #include "sync/syncable/syncable_changes_version.h"
23 #include "sync/syncable/syncable_proto_util.h"
24 #include "sync/util/time.h"
26 using std::set;
27 using std::string;
28 using std::vector;
30 namespace syncer {
32 using sessions::SyncSession;
33 using syncable::Entry;
34 using syncable::IS_DEL;
35 using syncable::IS_UNAPPLIED_UPDATE;
36 using syncable::IS_UNSYNCED;
37 using syncable::Id;
38 using syncable::SPECIFICS;
39 using syncable::UNIQUE_POSITION;
41 BuildCommitCommand::BuildCommitCommand(
42 syncable::BaseTransaction* trans,
43 const sessions::OrderedCommitSet& batch_commit_set,
44 sync_pb::ClientToServerMessage* commit_message,
45 ExtensionsActivity::Records* extensions_activity_buffer)
46 : trans_(trans),
47 batch_commit_set_(batch_commit_set),
48 commit_message_(commit_message),
49 extensions_activity_buffer_(extensions_activity_buffer) {
52 BuildCommitCommand::~BuildCommitCommand() {}
54 void BuildCommitCommand::AddExtensionsActivityToMessage(
55 SyncSession* session, sync_pb::CommitMessage* message) {
56 // We only send ExtensionsActivity to the server if bookmarks are being
57 // committed.
58 ExtensionsActivity* activity = session->context()->extensions_activity();
59 if (batch_commit_set_.HasBookmarkCommitId()) {
60 // This isn't perfect, since the set of extensions activity may not
61 // correlate exactly with the items being committed. That's OK as
62 // long as we're looking for a rough estimate of extensions activity,
63 // not an precise mapping of which commits were triggered by which
64 // extension.
66 // We will push this list of extensions activity back into the
67 // ExtensionsActivityMonitor if this commit fails. That's why we must keep
68 // a copy of these records in the session.
69 activity->GetAndClearRecords(extensions_activity_buffer_);
71 const ExtensionsActivity::Records& records =
72 *extensions_activity_buffer_;
73 for (ExtensionsActivity::Records::const_iterator it =
74 records.begin();
75 it != records.end(); ++it) {
76 sync_pb::ChromiumExtensionsActivity* activity_message =
77 message->add_extensions_activity();
78 activity_message->set_extension_id(it->second.extension_id);
79 activity_message->set_bookmark_writes_since_last_commit(
80 it->second.bookmark_write_count);
85 void BuildCommitCommand::AddClientConfigParamsToMessage(
86 SyncSession* session, sync_pb::CommitMessage* message) {
87 const ModelSafeRoutingInfo& routing_info = session->context()->routing_info();
88 sync_pb::ClientConfigParams* config_params = message->mutable_config_params();
89 for (std::map<ModelType, ModelSafeGroup>::const_iterator iter =
90 routing_info.begin(); iter != routing_info.end(); ++iter) {
91 if (ProxyTypes().Has(iter->first))
92 continue;
93 int field_number = GetSpecificsFieldNumberFromModelType(iter->first);
94 config_params->mutable_enabled_type_ids()->Add(field_number);
96 config_params->set_tabs_datatype_enabled(
97 routing_info.count(syncer::PROXY_TABS) > 0);
100 namespace {
101 void SetEntrySpecifics(const Entry& meta_entry,
102 sync_pb::SyncEntity* sync_entry) {
103 // Add the new style extension and the folder bit.
104 sync_entry->mutable_specifics()->CopyFrom(meta_entry.Get(SPECIFICS));
105 sync_entry->set_folder(meta_entry.Get(syncable::IS_DIR));
107 CHECK(!sync_entry->specifics().password().has_client_only_encrypted_data());
108 DCHECK_EQ(meta_entry.GetModelType(), GetModelType(*sync_entry));
110 } // namespace
112 SyncerError BuildCommitCommand::ExecuteImpl(SyncSession* session) {
113 commit_message_->set_share(session->context()->account_name());
114 commit_message_->set_message_contents(sync_pb::ClientToServerMessage::COMMIT);
116 sync_pb::CommitMessage* commit_message = commit_message_->mutable_commit();
117 commit_message->set_cache_guid(trans_->directory()->cache_guid());
118 AddExtensionsActivityToMessage(session, commit_message);
119 AddClientConfigParamsToMessage(session, commit_message);
121 for (size_t i = 0; i < batch_commit_set_.Size(); i++) {
122 Id id = batch_commit_set_.GetCommitIdAt(i);
123 sync_pb::SyncEntity* sync_entry = commit_message->add_entries();
125 Entry meta_entry(trans_, syncable::GET_BY_ID, id);
126 CHECK(meta_entry.good());
128 DCHECK_NE(0UL,
129 session->context()->routing_info().count(
130 meta_entry.GetModelType()))
131 << "Committing change to datatype that's not actively enabled.";
133 BuildCommitItem(meta_entry, sync_entry);
137 return SYNCER_OK;
140 // static.
141 void BuildCommitCommand::BuildCommitItem(
142 const syncable::Entry& meta_entry,
143 sync_pb::SyncEntity* sync_entry) {
144 syncable::Id id = meta_entry.Get(syncable::ID);
145 sync_entry->set_id_string(SyncableIdToProto(id));
147 string name = meta_entry.Get(syncable::NON_UNIQUE_NAME);
148 CHECK(!name.empty()); // Make sure this isn't an update.
149 // Note: Truncation is also performed in WriteNode::SetTitle(..). But this
150 // call is still necessary to handle any title changes that might originate
151 // elsewhere, or already be persisted in the directory.
152 TruncateUTF8ToByteSize(name, 255, &name);
153 sync_entry->set_name(name);
155 // Set the non_unique_name. If we do, the server ignores
156 // the |name| value (using |non_unique_name| instead), and will return
157 // in the CommitResponse a unique name if one is generated.
158 // We send both because it may aid in logging.
159 sync_entry->set_non_unique_name(name);
161 if (!meta_entry.Get(syncable::UNIQUE_CLIENT_TAG).empty()) {
162 sync_entry->set_client_defined_unique_tag(
163 meta_entry.Get(syncable::UNIQUE_CLIENT_TAG));
166 // Deleted items with server-unknown parent ids can be a problem so we set
167 // the parent to 0. (TODO(sync): Still true in protocol?).
168 Id new_parent_id;
169 if (meta_entry.Get(syncable::IS_DEL) &&
170 !meta_entry.Get(syncable::PARENT_ID).ServerKnows()) {
171 new_parent_id = syncable::BaseTransaction::root_id();
172 } else {
173 new_parent_id = meta_entry.Get(syncable::PARENT_ID);
175 sync_entry->set_parent_id_string(SyncableIdToProto(new_parent_id));
177 // If our parent has changed, send up the old one so the server
178 // can correctly deal with multiple parents.
179 // TODO(nick): With the server keeping track of the primary sync parent,
180 // it should not be necessary to provide the old_parent_id: the version
181 // number should suffice.
182 if (new_parent_id != meta_entry.Get(syncable::SERVER_PARENT_ID) &&
183 0 != meta_entry.Get(syncable::BASE_VERSION) &&
184 syncable::CHANGES_VERSION != meta_entry.Get(syncable::BASE_VERSION)) {
185 sync_entry->set_old_parent_id(
186 SyncableIdToProto(meta_entry.Get(syncable::SERVER_PARENT_ID)));
189 int64 version = meta_entry.Get(syncable::BASE_VERSION);
190 if (syncable::CHANGES_VERSION == version || 0 == version) {
191 // Undeletions are only supported for items that have a client tag.
192 DCHECK(!id.ServerKnows() ||
193 !meta_entry.Get(syncable::UNIQUE_CLIENT_TAG).empty())
194 << meta_entry;
196 // Version 0 means to create or undelete an object.
197 sync_entry->set_version(0);
198 } else {
199 DCHECK(id.ServerKnows()) << meta_entry;
200 sync_entry->set_version(meta_entry.Get(syncable::BASE_VERSION));
202 sync_entry->set_ctime(TimeToProtoTime(meta_entry.Get(syncable::CTIME)));
203 sync_entry->set_mtime(TimeToProtoTime(meta_entry.Get(syncable::MTIME)));
205 // Deletion is final on the server, let's move things and then delete them.
206 if (meta_entry.Get(IS_DEL)) {
207 sync_entry->set_deleted(true);
208 } else {
209 if (meta_entry.Get(SPECIFICS).has_bookmark()) {
210 // Both insert_after_item_id and position_in_parent fields are set only
211 // for legacy reasons. See comments in sync.proto for more information.
212 const Id& prev_id = meta_entry.GetPredecessorId();
213 string prev_id_string =
214 prev_id.IsRoot() ? string() : prev_id.GetServerId();
215 sync_entry->set_insert_after_item_id(prev_id_string);
216 sync_entry->set_position_in_parent(
217 meta_entry.Get(UNIQUE_POSITION).ToInt64());
218 meta_entry.Get(UNIQUE_POSITION).ToProto(
219 sync_entry->mutable_unique_position());
221 SetEntrySpecifics(meta_entry, sync_entry);
225 } // namespace syncer