Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(828)

Side by Side Diff: components/sync/core/base_node.cc

Issue 2407163004: [Sync] Move some directory-related things from core/ to syncable/. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/sync/core/base_node.h ('k') | components/sync/core/base_transaction.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 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 "components/sync/core/base_node.h"
6
7 #include <stack>
8
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "components/sync/base/time.h"
12 #include "components/sync/core/base_transaction.h"
13 #include "components/sync/core_impl/syncapi_internal.h"
14 #include "components/sync/protocol/app_specifics.pb.h"
15 #include "components/sync/protocol/autofill_specifics.pb.h"
16 #include "components/sync/protocol/bookmark_specifics.pb.h"
17 #include "components/sync/protocol/extension_specifics.pb.h"
18 #include "components/sync/protocol/nigori_specifics.pb.h"
19 #include "components/sync/protocol/password_specifics.pb.h"
20 #include "components/sync/protocol/session_specifics.pb.h"
21 #include "components/sync/protocol/theme_specifics.pb.h"
22 #include "components/sync/protocol/typed_url_specifics.pb.h"
23 #include "components/sync/syncable/directory.h"
24 #include "components/sync/syncable/entry.h"
25 #include "components/sync/syncable/syncable_base_transaction.h"
26 #include "components/sync/syncable/syncable_id.h"
27
28 using sync_pb::AutofillProfileSpecifics;
29
30 namespace syncer {
31
32 using syncable::SPECIFICS;
33
34 // Helper function to look up the int64_t metahandle of an object given the ID
35 // string.
36 static int64_t IdToMetahandle(syncable::BaseTransaction* trans,
37 const syncable::Id& id) {
38 if (id.IsNull())
39 return kInvalidId;
40 syncable::Entry entry(trans, syncable::GET_BY_ID, id);
41 if (!entry.good())
42 return kInvalidId;
43 return entry.GetMetahandle();
44 }
45
46 BaseNode::BaseNode() : password_data_(new sync_pb::PasswordSpecificsData) {}
47
48 BaseNode::~BaseNode() {}
49
50 bool BaseNode::DecryptIfNecessary() {
51 if (GetIsPermanentFolder())
52 return true; // Ignore unique folders.
53 const sync_pb::EntitySpecifics& specifics = GetEntry()->GetSpecifics();
54 if (specifics.has_password()) {
55 // Passwords have their own legacy encryption structure.
56 std::unique_ptr<sync_pb::PasswordSpecificsData> data(
57 DecryptPasswordSpecifics(specifics,
58 GetTransaction()->GetCryptographer()));
59 if (!data) {
60 GetTransaction()->GetWrappedTrans()->OnUnrecoverableError(
61 FROM_HERE, std::string("Failed to decrypt encrypted node of type ") +
62 ModelTypeToString(GetModelType()));
63 return false;
64 }
65 password_data_.swap(data);
66 return true;
67 }
68
69 // We assume any node with the encrypted field set has encrypted data and if
70 // not we have no work to do, with the exception of bookmarks. For bookmarks
71 // we must make sure the bookmarks data has the title field supplied. If not,
72 // we fill the unencrypted_data_ with a copy of the bookmark specifics that
73 // follows the new bookmarks format.
74 if (!specifics.has_encrypted()) {
75 if (GetModelType() == BOOKMARKS && !specifics.bookmark().has_title() &&
76 !GetTitle().empty()) { // Last check ensures this isn't a new node.
77 // We need to fill in the title.
78 std::string title = GetTitle();
79 std::string server_legal_title;
80 SyncAPINameToServerName(title, &server_legal_title);
81 DVLOG(1) << "Reading from legacy bookmark, manually returning title "
82 << title;
83 unencrypted_data_.CopyFrom(specifics);
84 unencrypted_data_.mutable_bookmark()->set_title(server_legal_title);
85 }
86 return true;
87 }
88
89 const sync_pb::EncryptedData& encrypted = specifics.encrypted();
90 std::string plaintext_data =
91 GetTransaction()->GetCryptographer()->DecryptToString(encrypted);
92 if (plaintext_data.length() == 0) {
93 GetTransaction()->GetWrappedTrans()->OnUnrecoverableError(
94 FROM_HERE, std::string("Failed to decrypt encrypted node of type ") +
95 ModelTypeToString(GetModelType()));
96 return false;
97 } else if (!unencrypted_data_.ParseFromString(plaintext_data)) {
98 GetTransaction()->GetWrappedTrans()->OnUnrecoverableError(
99 FROM_HERE, std::string("Failed to parse encrypted node of type ") +
100 ModelTypeToString(GetModelType()));
101 return false;
102 }
103 DVLOG(2) << "Decrypted specifics of type "
104 << ModelTypeToString(GetModelType())
105 << " with content: " << plaintext_data;
106 return true;
107 }
108
109 const sync_pb::EntitySpecifics& BaseNode::GetUnencryptedSpecifics(
110 const syncable::Entry* entry) const {
111 const sync_pb::EntitySpecifics& specifics = entry->GetSpecifics();
112 if (specifics.has_encrypted()) {
113 DCHECK_NE(GetModelTypeFromSpecifics(unencrypted_data_), UNSPECIFIED);
114 return unencrypted_data_;
115 } else {
116 // Due to the change in bookmarks format, we need to check to see if this is
117 // a legacy bookmarks (and has no title field in the proto). If it is, we
118 // return the unencrypted_data_, which was filled in with the title by
119 // DecryptIfNecessary().
120 if (GetModelType() == BOOKMARKS) {
121 const sync_pb::BookmarkSpecifics& bookmark_specifics =
122 specifics.bookmark();
123 if (bookmark_specifics.has_title() ||
124 GetTitle().empty() || // For the empty node case
125 GetIsPermanentFolder()) {
126 // It's possible we previously had to convert and set
127 // |unencrypted_data_| but then wrote our own data, so we allow
128 // |unencrypted_data_| to be non-empty.
129 return specifics;
130 } else {
131 DCHECK_EQ(GetModelTypeFromSpecifics(unencrypted_data_), BOOKMARKS);
132 return unencrypted_data_;
133 }
134 } else {
135 DCHECK_EQ(GetModelTypeFromSpecifics(unencrypted_data_), UNSPECIFIED);
136 return specifics;
137 }
138 }
139 }
140
141 int64_t BaseNode::GetParentId() const {
142 return IdToMetahandle(GetTransaction()->GetWrappedTrans(),
143 GetEntry()->GetParentId());
144 }
145
146 int64_t BaseNode::GetId() const {
147 return GetEntry()->GetMetahandle();
148 }
149
150 base::Time BaseNode::GetModificationTime() const {
151 return GetEntry()->GetMtime();
152 }
153
154 bool BaseNode::GetIsFolder() const {
155 return GetEntry()->GetIsDir();
156 }
157
158 bool BaseNode::GetIsPermanentFolder() const {
159 bool is_permanent_folder = !GetEntry()->GetUniqueServerTag().empty();
160 if (is_permanent_folder) {
161 // If the node is a permanent folder it must also have IS_DIR bit set,
162 // except some nigori nodes on old accounts.
163 DCHECK(GetIsFolder() || GetModelType() == NIGORI);
164 }
165 return is_permanent_folder;
166 }
167
168 std::string BaseNode::GetTitle() const {
169 std::string result;
170 // TODO(zea): refactor bookmarks to not need this functionality.
171 if (BOOKMARKS == GetModelType() &&
172 GetEntry()->GetSpecifics().has_encrypted()) {
173 // Special case for legacy bookmarks dealing with encryption.
174 ServerNameToSyncAPIName(GetBookmarkSpecifics().title(), &result);
175 } else {
176 ServerNameToSyncAPIName(GetEntry()->GetNonUniqueName(), &result);
177 }
178 return result;
179 }
180
181 bool BaseNode::HasChildren() const {
182 syncable::Directory* dir = GetTransaction()->GetDirectory();
183 syncable::BaseTransaction* trans = GetTransaction()->GetWrappedTrans();
184 return dir->HasChildren(trans, GetEntry()->GetId());
185 }
186
187 int64_t BaseNode::GetPredecessorId() const {
188 syncable::Id id_string = GetEntry()->GetPredecessorId();
189 if (id_string.IsNull())
190 return kInvalidId;
191 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string);
192 }
193
194 int64_t BaseNode::GetSuccessorId() const {
195 syncable::Id id_string = GetEntry()->GetSuccessorId();
196 if (id_string.IsNull())
197 return kInvalidId;
198 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string);
199 }
200
201 int64_t BaseNode::GetFirstChildId() const {
202 syncable::Id id_string = GetEntry()->GetFirstChildId();
203 if (id_string.IsNull())
204 return kInvalidId;
205 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string);
206 }
207
208 void BaseNode::GetChildIds(std::vector<int64_t>* result) const {
209 GetEntry()->GetChildHandles(result);
210 }
211
212 int BaseNode::GetTotalNodeCount() const {
213 return GetEntry()->GetTotalNodeCount();
214 }
215
216 int BaseNode::GetPositionIndex() const {
217 return GetEntry()->GetPositionIndex();
218 }
219
220 base::DictionaryValue* BaseNode::ToValue() const {
221 return GetEntry()->ToValue(GetTransaction()->GetCryptographer());
222 }
223
224 int64_t BaseNode::GetExternalId() const {
225 return GetEntry()->GetLocalExternalId();
226 }
227
228 const syncable::Id& BaseNode::GetSyncId() const {
229 return GetEntry()->GetId();
230 }
231
232 const sync_pb::BookmarkSpecifics& BaseNode::GetBookmarkSpecifics() const {
233 DCHECK_EQ(GetModelType(), BOOKMARKS);
234 return GetEntitySpecifics().bookmark();
235 }
236
237 const sync_pb::NigoriSpecifics& BaseNode::GetNigoriSpecifics() const {
238 DCHECK_EQ(GetModelType(), NIGORI);
239 return GetEntitySpecifics().nigori();
240 }
241
242 const sync_pb::PasswordSpecificsData& BaseNode::GetPasswordSpecifics() const {
243 DCHECK_EQ(GetModelType(), PASSWORDS);
244 return *password_data_;
245 }
246
247 const sync_pb::TypedUrlSpecifics& BaseNode::GetTypedUrlSpecifics() const {
248 DCHECK_EQ(GetModelType(), TYPED_URLS);
249 return GetEntitySpecifics().typed_url();
250 }
251
252 const sync_pb::ExperimentsSpecifics& BaseNode::GetExperimentsSpecifics() const {
253 DCHECK_EQ(GetModelType(), EXPERIMENTS);
254 return GetEntitySpecifics().experiments();
255 }
256
257 const sync_pb::EntitySpecifics& BaseNode::GetEntitySpecifics() const {
258 return GetUnencryptedSpecifics(GetEntry());
259 }
260
261 ModelType BaseNode::GetModelType() const {
262 return GetEntry()->GetModelType();
263 }
264
265 const AttachmentIdList BaseNode::GetAttachmentIds() const {
266 AttachmentIdList result;
267 const sync_pb::AttachmentMetadata& metadata =
268 GetEntry()->GetAttachmentMetadata();
269 for (int i = 0; i < metadata.record_size(); ++i) {
270 result.push_back(AttachmentId::CreateFromProto(metadata.record(i).id()));
271 }
272 return result;
273 }
274
275 void BaseNode::SetUnencryptedSpecifics(
276 const sync_pb::EntitySpecifics& specifics) {
277 ModelType type = GetModelTypeFromSpecifics(specifics);
278 DCHECK_NE(UNSPECIFIED, type);
279 if (GetModelType() != UNSPECIFIED) {
280 DCHECK_EQ(GetModelType(), type);
281 }
282 unencrypted_data_.CopyFrom(specifics);
283 }
284
285 } // namespace syncer
OLDNEW
« no previous file with comments | « components/sync/core/base_node.h ('k') | components/sync/core/base_transaction.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698