OLD | NEW |
| (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 "chrome/browser/sync/syncable/model_type.h" | |
6 | |
7 #include "base/string_split.h" | |
8 #include "base/values.h" | |
9 #include "chrome/browser/sync/engine/syncproto.h" | |
10 #include "sync/protocol/app_notification_specifics.pb.h" | |
11 #include "sync/protocol/app_setting_specifics.pb.h" | |
12 #include "sync/protocol/app_specifics.pb.h" | |
13 #include "sync/protocol/autofill_specifics.pb.h" | |
14 #include "sync/protocol/bookmark_specifics.pb.h" | |
15 #include "sync/protocol/extension_setting_specifics.pb.h" | |
16 #include "sync/protocol/extension_specifics.pb.h" | |
17 #include "sync/protocol/nigori_specifics.pb.h" | |
18 #include "sync/protocol/password_specifics.pb.h" | |
19 #include "sync/protocol/preference_specifics.pb.h" | |
20 #include "sync/protocol/search_engine_specifics.pb.h" | |
21 #include "sync/protocol/session_specifics.pb.h" | |
22 #include "sync/protocol/sync.pb.h" | |
23 #include "sync/protocol/theme_specifics.pb.h" | |
24 #include "sync/protocol/typed_url_specifics.pb.h" | |
25 | |
26 namespace syncable { | |
27 | |
28 void AddDefaultFieldValue(syncable::ModelType datatype, | |
29 sync_pb::EntitySpecifics* specifics) { | |
30 switch (datatype) { | |
31 case BOOKMARKS: | |
32 specifics->mutable_bookmark(); | |
33 break; | |
34 case PASSWORDS: | |
35 specifics->mutable_password(); | |
36 break; | |
37 case PREFERENCES: | |
38 specifics->mutable_preference(); | |
39 break; | |
40 case AUTOFILL: | |
41 specifics->mutable_autofill(); | |
42 break; | |
43 case AUTOFILL_PROFILE: | |
44 specifics->mutable_autofill_profile(); | |
45 break; | |
46 case THEMES: | |
47 specifics->mutable_theme(); | |
48 break; | |
49 case TYPED_URLS: | |
50 specifics->mutable_typed_url(); | |
51 break; | |
52 case EXTENSIONS: | |
53 specifics->mutable_extension(); | |
54 break; | |
55 case NIGORI: | |
56 specifics->mutable_nigori(); | |
57 break; | |
58 case SEARCH_ENGINES: | |
59 specifics->mutable_search_engine(); | |
60 break; | |
61 case SESSIONS: | |
62 specifics->mutable_session(); | |
63 break; | |
64 case APPS: | |
65 specifics->mutable_app(); | |
66 break; | |
67 case APP_SETTINGS: | |
68 specifics->mutable_app_setting(); | |
69 break; | |
70 case EXTENSION_SETTINGS: | |
71 specifics->mutable_extension_setting(); | |
72 break; | |
73 case APP_NOTIFICATIONS: | |
74 specifics->mutable_app_notification(); | |
75 break; | |
76 default: | |
77 NOTREACHED() << "No known extension for model type."; | |
78 } | |
79 } | |
80 | |
81 ModelType GetModelTypeFromSpecificsFieldNumber(int field_number) { | |
82 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { | |
83 ModelType model_type = ModelTypeFromInt(i); | |
84 if (GetSpecificsFieldNumberFromModelType(model_type) == field_number) | |
85 return model_type; | |
86 } | |
87 NOTREACHED(); | |
88 return UNSPECIFIED; | |
89 } | |
90 | |
91 int GetSpecificsFieldNumberFromModelType(ModelType model_type) { | |
92 switch (model_type) { | |
93 case BOOKMARKS: | |
94 return sync_pb::EntitySpecifics::kBookmarkFieldNumber; | |
95 break; | |
96 case PASSWORDS: | |
97 return sync_pb::EntitySpecifics::kPasswordFieldNumber; | |
98 break; | |
99 case PREFERENCES: | |
100 return sync_pb::EntitySpecifics::kPreferenceFieldNumber; | |
101 break; | |
102 case AUTOFILL: | |
103 return sync_pb::EntitySpecifics::kAutofillFieldNumber; | |
104 break; | |
105 case AUTOFILL_PROFILE: | |
106 return sync_pb::EntitySpecifics::kAutofillProfileFieldNumber; | |
107 break; | |
108 case THEMES: | |
109 return sync_pb::EntitySpecifics::kThemeFieldNumber; | |
110 break; | |
111 case TYPED_URLS: | |
112 return sync_pb::EntitySpecifics::kTypedUrlFieldNumber; | |
113 break; | |
114 case EXTENSIONS: | |
115 return sync_pb::EntitySpecifics::kExtensionFieldNumber; | |
116 break; | |
117 case NIGORI: | |
118 return sync_pb::EntitySpecifics::kNigoriFieldNumber; | |
119 break; | |
120 case SEARCH_ENGINES: | |
121 return sync_pb::EntitySpecifics::kSearchEngineFieldNumber; | |
122 break; | |
123 case SESSIONS: | |
124 return sync_pb::EntitySpecifics::kSessionFieldNumber; | |
125 break; | |
126 case APPS: | |
127 return sync_pb::EntitySpecifics::kAppFieldNumber; | |
128 break; | |
129 case APP_SETTINGS: | |
130 return sync_pb::EntitySpecifics::kAppSettingFieldNumber; | |
131 break; | |
132 case EXTENSION_SETTINGS: | |
133 return sync_pb::EntitySpecifics::kExtensionSettingFieldNumber; | |
134 break; | |
135 case APP_NOTIFICATIONS: | |
136 return sync_pb::EntitySpecifics::kAppNotificationFieldNumber; | |
137 break; | |
138 default: | |
139 NOTREACHED() << "No known extension for model type."; | |
140 return 0; | |
141 } | |
142 NOTREACHED() << "Needed for linux_keep_shadow_stacks because of " | |
143 << "http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20681"; | |
144 return 0; | |
145 } | |
146 | |
147 // Note: keep this consistent with GetModelType in syncable.cc! | |
148 ModelType GetModelType(const sync_pb::SyncEntity& sync_pb_entity) { | |
149 const browser_sync::SyncEntity& sync_entity = | |
150 static_cast<const browser_sync::SyncEntity&>(sync_pb_entity); | |
151 DCHECK(!sync_entity.id().IsRoot()); // Root shouldn't ever go over the wire. | |
152 | |
153 if (sync_entity.deleted()) | |
154 return UNSPECIFIED; | |
155 | |
156 // Backwards compatibility with old (pre-specifics) protocol. | |
157 if (sync_entity.has_bookmarkdata()) | |
158 return BOOKMARKS; | |
159 | |
160 ModelType specifics_type = GetModelTypeFromSpecifics(sync_entity.specifics()); | |
161 if (specifics_type != UNSPECIFIED) | |
162 return specifics_type; | |
163 | |
164 // Loose check for server-created top-level folders that aren't | |
165 // bound to a particular model type. | |
166 if (!sync_entity.server_defined_unique_tag().empty() && | |
167 sync_entity.IsFolder()) { | |
168 return TOP_LEVEL_FOLDER; | |
169 } | |
170 | |
171 // This is an item of a datatype we can't understand. Maybe it's | |
172 // from the future? Either we mis-encoded the object, or the | |
173 // server sent us entries it shouldn't have. | |
174 NOTREACHED() << "Unknown datatype in sync proto."; | |
175 return UNSPECIFIED; | |
176 } | |
177 | |
178 ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics) { | |
179 if (specifics.has_bookmark()) | |
180 return BOOKMARKS; | |
181 | |
182 if (specifics.has_password()) | |
183 return PASSWORDS; | |
184 | |
185 if (specifics.has_preference()) | |
186 return PREFERENCES; | |
187 | |
188 if (specifics.has_autofill()) | |
189 return AUTOFILL; | |
190 | |
191 if (specifics.has_autofill_profile()) | |
192 return AUTOFILL_PROFILE; | |
193 | |
194 if (specifics.has_theme()) | |
195 return THEMES; | |
196 | |
197 if (specifics.has_typed_url()) | |
198 return TYPED_URLS; | |
199 | |
200 if (specifics.has_extension()) | |
201 return EXTENSIONS; | |
202 | |
203 if (specifics.has_nigori()) | |
204 return NIGORI; | |
205 | |
206 if (specifics.has_app()) | |
207 return APPS; | |
208 | |
209 if (specifics.has_search_engine()) | |
210 return SEARCH_ENGINES; | |
211 | |
212 if (specifics.has_session()) | |
213 return SESSIONS; | |
214 | |
215 if (specifics.has_app_setting()) | |
216 return APP_SETTINGS; | |
217 | |
218 if (specifics.has_extension_setting()) | |
219 return EXTENSION_SETTINGS; | |
220 | |
221 if (specifics.has_app_notification()) | |
222 return APP_NOTIFICATIONS; | |
223 | |
224 return UNSPECIFIED; | |
225 } | |
226 | |
227 bool ShouldMaintainPosition(ModelType model_type) { | |
228 return model_type == BOOKMARKS; | |
229 } | |
230 | |
231 const char* ModelTypeToString(ModelType model_type) { | |
232 // This is used in serialization routines as well as for displaying debug | |
233 // information. Do not attempt to change these string values unless you know | |
234 // what you're doing. | |
235 switch (model_type) { | |
236 case TOP_LEVEL_FOLDER: | |
237 return "Top Level Folder"; | |
238 case UNSPECIFIED: | |
239 return "Unspecified"; | |
240 case BOOKMARKS: | |
241 return "Bookmarks"; | |
242 case PREFERENCES: | |
243 return "Preferences"; | |
244 case PASSWORDS: | |
245 return "Passwords"; | |
246 case AUTOFILL: | |
247 return "Autofill"; | |
248 case THEMES: | |
249 return "Themes"; | |
250 case TYPED_URLS: | |
251 return "Typed URLs"; | |
252 case EXTENSIONS: | |
253 return "Extensions"; | |
254 case NIGORI: | |
255 return "Encryption keys"; | |
256 case SEARCH_ENGINES: | |
257 return "Search Engines"; | |
258 case SESSIONS: | |
259 return "Sessions"; | |
260 case APPS: | |
261 return "Apps"; | |
262 case AUTOFILL_PROFILE: | |
263 return "Autofill Profiles"; | |
264 case APP_SETTINGS: | |
265 return "App settings"; | |
266 case EXTENSION_SETTINGS: | |
267 return "Extension settings"; | |
268 case APP_NOTIFICATIONS: | |
269 return "App Notifications"; | |
270 default: | |
271 break; | |
272 } | |
273 NOTREACHED() << "No known extension for model type."; | |
274 return "INVALID"; | |
275 } | |
276 | |
277 StringValue* ModelTypeToValue(ModelType model_type) { | |
278 if (model_type >= syncable::FIRST_REAL_MODEL_TYPE) { | |
279 return Value::CreateStringValue(ModelTypeToString(model_type)); | |
280 } else if (model_type == syncable::TOP_LEVEL_FOLDER) { | |
281 return Value::CreateStringValue("Top-level folder"); | |
282 } else if (model_type == syncable::UNSPECIFIED) { | |
283 return Value::CreateStringValue("Unspecified"); | |
284 } | |
285 NOTREACHED(); | |
286 return Value::CreateStringValue(""); | |
287 } | |
288 | |
289 ModelType ModelTypeFromValue(const Value& value) { | |
290 if (value.IsType(Value::TYPE_STRING)) { | |
291 std::string result; | |
292 CHECK(value.GetAsString(&result)); | |
293 return ModelTypeFromString(result); | |
294 } else if (value.IsType(Value::TYPE_INTEGER)) { | |
295 int result; | |
296 CHECK(value.GetAsInteger(&result)); | |
297 return ModelTypeFromInt(result); | |
298 } else { | |
299 NOTREACHED() << "Unsupported value type: " << value.GetType(); | |
300 return UNSPECIFIED; | |
301 } | |
302 } | |
303 | |
304 ModelType ModelTypeFromString(const std::string& model_type_string) { | |
305 if (model_type_string == "Bookmarks") | |
306 return BOOKMARKS; | |
307 else if (model_type_string == "Preferences") | |
308 return PREFERENCES; | |
309 else if (model_type_string == "Passwords") | |
310 return PASSWORDS; | |
311 else if (model_type_string == "Autofill") | |
312 return AUTOFILL; | |
313 else if (model_type_string == "Autofill Profiles") | |
314 return AUTOFILL_PROFILE; | |
315 else if (model_type_string == "Themes") | |
316 return THEMES; | |
317 else if (model_type_string == "Typed URLs") | |
318 return TYPED_URLS; | |
319 else if (model_type_string == "Extensions") | |
320 return EXTENSIONS; | |
321 else if (model_type_string == "Encryption keys") | |
322 return NIGORI; | |
323 else if (model_type_string == "Search Engines") | |
324 return SEARCH_ENGINES; | |
325 else if (model_type_string == "Sessions") | |
326 return SESSIONS; | |
327 else if (model_type_string == "Apps") | |
328 return APPS; | |
329 else if (model_type_string == "App settings") | |
330 return APP_SETTINGS; | |
331 else if (model_type_string == "Extension settings") | |
332 return EXTENSION_SETTINGS; | |
333 else if (model_type_string == "App Notifications") | |
334 return APP_NOTIFICATIONS; | |
335 else | |
336 NOTREACHED() << "No known model type corresponding to " | |
337 << model_type_string << "."; | |
338 return UNSPECIFIED; | |
339 } | |
340 | |
341 std::string ModelTypeSetToString(ModelTypeSet model_types) { | |
342 std::string result; | |
343 for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) { | |
344 if (!result.empty()) { | |
345 result += ", "; | |
346 } | |
347 result += ModelTypeToString(it.Get()); | |
348 } | |
349 return result; | |
350 } | |
351 | |
352 base::ListValue* ModelTypeSetToValue(ModelTypeSet model_types) { | |
353 ListValue* value = new ListValue(); | |
354 for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) { | |
355 value->Append( | |
356 Value::CreateStringValue(ModelTypeToString(it.Get()))); | |
357 } | |
358 return value; | |
359 } | |
360 | |
361 ModelTypeSet ModelTypeSetFromValue(const base::ListValue& value) { | |
362 ModelTypeSet result; | |
363 for (ListValue::const_iterator i = value.begin(); i != value.end(); ++i) { | |
364 result.Put(ModelTypeFromValue(**i)); | |
365 } | |
366 return result; | |
367 } | |
368 | |
369 // TODO(zea): remove all hardcoded tags in model associators and have them use | |
370 // this instead. | |
371 std::string ModelTypeToRootTag(ModelType type) { | |
372 switch (type) { | |
373 case BOOKMARKS: | |
374 return "google_chrome_bookmarks"; | |
375 case PREFERENCES: | |
376 return "google_chrome_preferences"; | |
377 case PASSWORDS: | |
378 return "google_chrome_passwords"; | |
379 case AUTOFILL: | |
380 return "google_chrome_autofill"; | |
381 case THEMES: | |
382 return "google_chrome_themes"; | |
383 case TYPED_URLS: | |
384 return "google_chrome_typed_urls"; | |
385 case EXTENSIONS: | |
386 return "google_chrome_extensions"; | |
387 case NIGORI: | |
388 return "google_chrome_nigori"; | |
389 case SEARCH_ENGINES: | |
390 return "google_chrome_search_engines"; | |
391 case SESSIONS: | |
392 return "google_chrome_sessions"; | |
393 case APPS: | |
394 return "google_chrome_apps"; | |
395 case AUTOFILL_PROFILE: | |
396 return "google_chrome_autofill_profiles"; | |
397 case APP_SETTINGS: | |
398 return "google_chrome_app_settings"; | |
399 case EXTENSION_SETTINGS: | |
400 return "google_chrome_extension_settings"; | |
401 case APP_NOTIFICATIONS: | |
402 return "google_chrome_app_notifications"; | |
403 default: | |
404 break; | |
405 } | |
406 NOTREACHED() << "No known extension for model type."; | |
407 return "INVALID"; | |
408 } | |
409 | |
410 // TODO(akalin): Figure out a better way to do these mappings. | |
411 | |
412 namespace { | |
413 const char kBookmarkNotificationType[] = "BOOKMARK"; | |
414 const char kPreferenceNotificationType[] = "PREFERENCE"; | |
415 const char kPasswordNotificationType[] = "PASSWORD"; | |
416 const char kAutofillNotificationType[] = "AUTOFILL"; | |
417 const char kThemeNotificationType[] = "THEME"; | |
418 const char kTypedUrlNotificationType[] = "TYPED_URL"; | |
419 const char kExtensionNotificationType[] = "EXTENSION"; | |
420 const char kExtensionSettingNotificationType[] = "EXTENSION_SETTING"; | |
421 const char kNigoriNotificationType[] = "NIGORI"; | |
422 const char kAppSettingNotificationType[] = "APP_SETTING"; | |
423 const char kAppNotificationType[] = "APP"; | |
424 const char kSearchEngineNotificationType[] = "SEARCH_ENGINE"; | |
425 const char kSessionNotificationType[] = "SESSION"; | |
426 const char kAutofillProfileNotificationType[] = "AUTOFILL_PROFILE"; | |
427 const char kAppNotificationNotificationType[] = "APP_NOTIFICATION"; | |
428 } // namespace | |
429 | |
430 bool RealModelTypeToNotificationType(ModelType model_type, | |
431 std::string* notification_type) { | |
432 switch (model_type) { | |
433 case BOOKMARKS: | |
434 *notification_type = kBookmarkNotificationType; | |
435 return true; | |
436 case PREFERENCES: | |
437 *notification_type = kPreferenceNotificationType; | |
438 return true; | |
439 case PASSWORDS: | |
440 *notification_type = kPasswordNotificationType; | |
441 return true; | |
442 case AUTOFILL: | |
443 *notification_type = kAutofillNotificationType; | |
444 return true; | |
445 case THEMES: | |
446 *notification_type = kThemeNotificationType; | |
447 return true; | |
448 case TYPED_URLS: | |
449 *notification_type = kTypedUrlNotificationType; | |
450 return true; | |
451 case EXTENSIONS: | |
452 *notification_type = kExtensionNotificationType; | |
453 return true; | |
454 case NIGORI: | |
455 *notification_type = kNigoriNotificationType; | |
456 return true; | |
457 case APP_SETTINGS: | |
458 *notification_type = kAppNotificationType; | |
459 return true; | |
460 case APPS: | |
461 *notification_type = kAppNotificationType; | |
462 return true; | |
463 case SEARCH_ENGINES: | |
464 *notification_type = kSearchEngineNotificationType; | |
465 return true; | |
466 case SESSIONS: | |
467 *notification_type = kSessionNotificationType; | |
468 return true; | |
469 case AUTOFILL_PROFILE: | |
470 *notification_type = kAutofillProfileNotificationType; | |
471 return true; | |
472 case EXTENSION_SETTINGS: | |
473 *notification_type = kExtensionSettingNotificationType; | |
474 return true; | |
475 case APP_NOTIFICATIONS: | |
476 *notification_type = kAppNotificationNotificationType; | |
477 return true; | |
478 default: | |
479 break; | |
480 } | |
481 notification_type->clear(); | |
482 return false; | |
483 } | |
484 | |
485 bool NotificationTypeToRealModelType(const std::string& notification_type, | |
486 ModelType* model_type) { | |
487 if (notification_type == kBookmarkNotificationType) { | |
488 *model_type = BOOKMARKS; | |
489 return true; | |
490 } else if (notification_type == kPreferenceNotificationType) { | |
491 *model_type = PREFERENCES; | |
492 return true; | |
493 } else if (notification_type == kPasswordNotificationType) { | |
494 *model_type = PASSWORDS; | |
495 return true; | |
496 } else if (notification_type == kAutofillNotificationType) { | |
497 *model_type = AUTOFILL; | |
498 return true; | |
499 } else if (notification_type == kThemeNotificationType) { | |
500 *model_type = THEMES; | |
501 return true; | |
502 } else if (notification_type == kTypedUrlNotificationType) { | |
503 *model_type = TYPED_URLS; | |
504 return true; | |
505 } else if (notification_type == kExtensionNotificationType) { | |
506 *model_type = EXTENSIONS; | |
507 return true; | |
508 } else if (notification_type == kNigoriNotificationType) { | |
509 *model_type = NIGORI; | |
510 return true; | |
511 } else if (notification_type == kAppNotificationType) { | |
512 *model_type = APPS; | |
513 return true; | |
514 } else if (notification_type == kSearchEngineNotificationType) { | |
515 *model_type = SEARCH_ENGINES; | |
516 return true; | |
517 } else if (notification_type == kSessionNotificationType) { | |
518 *model_type = SESSIONS; | |
519 return true; | |
520 } else if (notification_type == kAutofillProfileNotificationType) { | |
521 *model_type = AUTOFILL_PROFILE; | |
522 return true; | |
523 } else if (notification_type == kAppSettingNotificationType) { | |
524 *model_type = APP_SETTINGS; | |
525 return true; | |
526 } else if (notification_type == kExtensionSettingNotificationType) { | |
527 *model_type = EXTENSION_SETTINGS; | |
528 return true; | |
529 } else if (notification_type == kAppNotificationNotificationType) { | |
530 *model_type = APP_NOTIFICATIONS; | |
531 return true; | |
532 } else { | |
533 *model_type = UNSPECIFIED; | |
534 return false; | |
535 } | |
536 } | |
537 | |
538 bool IsRealDataType(ModelType model_type) { | |
539 return model_type >= FIRST_REAL_MODEL_TYPE && model_type < MODEL_TYPE_COUNT; | |
540 } | |
541 | |
542 } // namespace syncable | |
OLD | NEW |