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 "sync/internal_api/public/base/model_type.h"
6
7 #include "base/strings/string_split.h"
8 #include "base/values.h"
9 #include "sync/protocol/app_notification_specifics.pb.h"
10 #include "sync/protocol/app_setting_specifics.pb.h"
11 #include "sync/protocol/app_specifics.pb.h"
12 #include "sync/protocol/autofill_specifics.pb.h"
13 #include "sync/protocol/bookmark_specifics.pb.h"
14 #include "sync/protocol/extension_setting_specifics.pb.h"
15 #include "sync/protocol/extension_specifics.pb.h"
16 #include "sync/protocol/nigori_specifics.pb.h"
17 #include "sync/protocol/password_specifics.pb.h"
18 #include "sync/protocol/preference_specifics.pb.h"
19 #include "sync/protocol/search_engine_specifics.pb.h"
20 #include "sync/protocol/session_specifics.pb.h"
21 #include "sync/protocol/sync.pb.h"
22 #include "sync/protocol/theme_specifics.pb.h"
23 #include "sync/protocol/typed_url_specifics.pb.h"
24 #include "sync/syncable/syncable_proto_util.h"
25
26 namespace syncer {
27
AddDefaultFieldValue(ModelType datatype,sync_pb::EntitySpecifics * specifics)28 void AddDefaultFieldValue(ModelType datatype,
29 sync_pb::EntitySpecifics* specifics) {
30 if (!ProtocolTypes().Has(datatype)) {
31 NOTREACHED() << "Only protocol types have field values.";
32 return;
33 }
34 switch (datatype) {
35 case BOOKMARKS:
36 specifics->mutable_bookmark();
37 break;
38 case PASSWORDS:
39 specifics->mutable_password();
40 break;
41 case PREFERENCES:
42 specifics->mutable_preference();
43 break;
44 case AUTOFILL:
45 specifics->mutable_autofill();
46 break;
47 case AUTOFILL_PROFILE:
48 specifics->mutable_autofill_profile();
49 break;
50 case THEMES:
51 specifics->mutable_theme();
52 break;
53 case TYPED_URLS:
54 specifics->mutable_typed_url();
55 break;
56 case EXTENSIONS:
57 specifics->mutable_extension();
58 break;
59 case NIGORI:
60 specifics->mutable_nigori();
61 break;
62 case SEARCH_ENGINES:
63 specifics->mutable_search_engine();
64 break;
65 case SESSIONS:
66 specifics->mutable_session();
67 break;
68 case APPS:
69 specifics->mutable_app();
70 break;
71 case APP_LIST:
72 specifics->mutable_app_list();
73 break;
74 case APP_SETTINGS:
75 specifics->mutable_app_setting();
76 break;
77 case EXTENSION_SETTINGS:
78 specifics->mutable_extension_setting();
79 break;
80 case APP_NOTIFICATIONS:
81 specifics->mutable_app_notification();
82 break;
83 case HISTORY_DELETE_DIRECTIVES:
84 specifics->mutable_history_delete_directive();
85 break;
86 case SYNCED_NOTIFICATIONS:
87 specifics->mutable_synced_notification();
88 break;
89 case DEVICE_INFO:
90 specifics->mutable_device_info();
91 break;
92 case EXPERIMENTS:
93 specifics->mutable_experiments();
94 break;
95 case PRIORITY_PREFERENCES:
96 specifics->mutable_priority_preference();
97 break;
98 case DICTIONARY:
99 specifics->mutable_dictionary();
100 break;
101 case FAVICON_IMAGES:
102 specifics->mutable_favicon_image();
103 break;
104 case FAVICON_TRACKING:
105 specifics->mutable_favicon_tracking();
106 break;
107 case MANAGED_USER_SETTINGS:
108 specifics->mutable_managed_user_setting();
109 break;
110 case MANAGED_USERS:
111 specifics->mutable_managed_user();
112 break;
113 case ARTICLES:
114 specifics->mutable_article();
115 break;
116 default:
117 NOTREACHED() << "No known extension for model type.";
118 }
119 }
120
GetModelTypeFromSpecificsFieldNumber(int field_number)121 ModelType GetModelTypeFromSpecificsFieldNumber(int field_number) {
122 ModelTypeSet protocol_types = ProtocolTypes();
123 for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good();
124 iter.Inc()) {
125 if (GetSpecificsFieldNumberFromModelType(iter.Get()) == field_number)
126 return iter.Get();
127 }
128 return UNSPECIFIED;
129 }
130
GetSpecificsFieldNumberFromModelType(ModelType model_type)131 int GetSpecificsFieldNumberFromModelType(ModelType model_type) {
132 if (!ProtocolTypes().Has(model_type)) {
133 NOTREACHED() << "Only protocol types have field values.";
134 return 0;
135 }
136 switch (model_type) {
137 case BOOKMARKS:
138 return sync_pb::EntitySpecifics::kBookmarkFieldNumber;
139 break;
140 case PASSWORDS:
141 return sync_pb::EntitySpecifics::kPasswordFieldNumber;
142 break;
143 case PREFERENCES:
144 return sync_pb::EntitySpecifics::kPreferenceFieldNumber;
145 break;
146 case AUTOFILL:
147 return sync_pb::EntitySpecifics::kAutofillFieldNumber;
148 break;
149 case AUTOFILL_PROFILE:
150 return sync_pb::EntitySpecifics::kAutofillProfileFieldNumber;
151 break;
152 case THEMES:
153 return sync_pb::EntitySpecifics::kThemeFieldNumber;
154 break;
155 case TYPED_URLS:
156 return sync_pb::EntitySpecifics::kTypedUrlFieldNumber;
157 break;
158 case EXTENSIONS:
159 return sync_pb::EntitySpecifics::kExtensionFieldNumber;
160 break;
161 case NIGORI:
162 return sync_pb::EntitySpecifics::kNigoriFieldNumber;
163 break;
164 case SEARCH_ENGINES:
165 return sync_pb::EntitySpecifics::kSearchEngineFieldNumber;
166 break;
167 case SESSIONS:
168 return sync_pb::EntitySpecifics::kSessionFieldNumber;
169 break;
170 case APPS:
171 return sync_pb::EntitySpecifics::kAppFieldNumber;
172 break;
173 case APP_LIST:
174 return sync_pb::EntitySpecifics::kAppListFieldNumber;
175 break;
176 case APP_SETTINGS:
177 return sync_pb::EntitySpecifics::kAppSettingFieldNumber;
178 break;
179 case EXTENSION_SETTINGS:
180 return sync_pb::EntitySpecifics::kExtensionSettingFieldNumber;
181 break;
182 case APP_NOTIFICATIONS:
183 return sync_pb::EntitySpecifics::kAppNotificationFieldNumber;
184 break;
185 case HISTORY_DELETE_DIRECTIVES:
186 return sync_pb::EntitySpecifics::kHistoryDeleteDirectiveFieldNumber;
187 case SYNCED_NOTIFICATIONS:
188 return sync_pb::EntitySpecifics::kSyncedNotificationFieldNumber;
189 case DEVICE_INFO:
190 return sync_pb::EntitySpecifics::kDeviceInfoFieldNumber;
191 break;
192 case EXPERIMENTS:
193 return sync_pb::EntitySpecifics::kExperimentsFieldNumber;
194 break;
195 case PRIORITY_PREFERENCES:
196 return sync_pb::EntitySpecifics::kPriorityPreferenceFieldNumber;
197 break;
198 case DICTIONARY:
199 return sync_pb::EntitySpecifics::kDictionaryFieldNumber;
200 break;
201 case FAVICON_IMAGES:
202 return sync_pb::EntitySpecifics::kFaviconImageFieldNumber;
203 case FAVICON_TRACKING:
204 return sync_pb::EntitySpecifics::kFaviconTrackingFieldNumber;
205 case MANAGED_USER_SETTINGS:
206 return sync_pb::EntitySpecifics::kManagedUserSettingFieldNumber;
207 case MANAGED_USERS:
208 return sync_pb::EntitySpecifics::kManagedUserFieldNumber;
209 case ARTICLES:
210 return sync_pb::EntitySpecifics::kArticleFieldNumber;
211 default:
212 NOTREACHED() << "No known extension for model type.";
213 return 0;
214 }
215 NOTREACHED() << "Needed for linux_keep_shadow_stacks because of "
216 << "http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20681";
217 return 0;
218 }
219
ToFullModelTypeSet(ModelTypeSet in)220 FullModelTypeSet ToFullModelTypeSet(ModelTypeSet in) {
221 FullModelTypeSet out;
222 for (ModelTypeSet::Iterator i = in.First(); i.Good(); i.Inc()) {
223 out.Put(i.Get());
224 }
225 return out;
226 }
227
228 // Note: keep this consistent with GetModelType in entry.cc!
GetModelType(const sync_pb::SyncEntity & sync_entity)229 ModelType GetModelType(const sync_pb::SyncEntity& sync_entity) {
230 DCHECK(!IsRoot(sync_entity)); // Root shouldn't ever go over the wire.
231
232 // Backwards compatibility with old (pre-specifics) protocol.
233 if (sync_entity.has_bookmarkdata())
234 return BOOKMARKS;
235
236 ModelType specifics_type = GetModelTypeFromSpecifics(sync_entity.specifics());
237 if (specifics_type != UNSPECIFIED)
238 return specifics_type;
239
240 // Loose check for server-created top-level folders that aren't
241 // bound to a particular model type.
242 if (!sync_entity.server_defined_unique_tag().empty() &&
243 IsFolder(sync_entity)) {
244 return TOP_LEVEL_FOLDER;
245 }
246
247 // This is an item of a datatype we can't understand. Maybe it's
248 // from the future? Either we mis-encoded the object, or the
249 // server sent us entries it shouldn't have.
250 NOTREACHED() << "Unknown datatype in sync proto.";
251 return UNSPECIFIED;
252 }
253
GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics & specifics)254 ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics) {
255 if (specifics.has_bookmark())
256 return BOOKMARKS;
257
258 if (specifics.has_password())
259 return PASSWORDS;
260
261 if (specifics.has_preference())
262 return PREFERENCES;
263
264 if (specifics.has_autofill())
265 return AUTOFILL;
266
267 if (specifics.has_autofill_profile())
268 return AUTOFILL_PROFILE;
269
270 if (specifics.has_theme())
271 return THEMES;
272
273 if (specifics.has_typed_url())
274 return TYPED_URLS;
275
276 if (specifics.has_extension())
277 return EXTENSIONS;
278
279 if (specifics.has_nigori())
280 return NIGORI;
281
282 if (specifics.has_app())
283 return APPS;
284
285 if (specifics.has_app_list())
286 return APP_LIST;
287
288 if (specifics.has_search_engine())
289 return SEARCH_ENGINES;
290
291 if (specifics.has_session())
292 return SESSIONS;
293
294 if (specifics.has_app_setting())
295 return APP_SETTINGS;
296
297 if (specifics.has_extension_setting())
298 return EXTENSION_SETTINGS;
299
300 if (specifics.has_app_notification())
301 return APP_NOTIFICATIONS;
302
303 if (specifics.has_history_delete_directive())
304 return HISTORY_DELETE_DIRECTIVES;
305
306 if (specifics.has_synced_notification())
307 return SYNCED_NOTIFICATIONS;
308
309 if (specifics.has_device_info())
310 return DEVICE_INFO;
311
312 if (specifics.has_experiments())
313 return EXPERIMENTS;
314
315 if (specifics.has_priority_preference())
316 return PRIORITY_PREFERENCES;
317
318 if (specifics.has_dictionary())
319 return DICTIONARY;
320
321 if (specifics.has_favicon_image())
322 return FAVICON_IMAGES;
323
324 if (specifics.has_favicon_tracking())
325 return FAVICON_TRACKING;
326
327 if (specifics.has_managed_user_setting())
328 return MANAGED_USER_SETTINGS;
329
330 if (specifics.has_managed_user())
331 return MANAGED_USERS;
332
333 if (specifics.has_article())
334 return ARTICLES;
335
336 return UNSPECIFIED;
337 }
338
ProtocolTypes()339 ModelTypeSet ProtocolTypes() {
340 ModelTypeSet set = ModelTypeSet::All();
341 set.RemoveAll(ProxyTypes());
342 return set;
343 }
344
UserTypes()345 ModelTypeSet UserTypes() {
346 ModelTypeSet set;
347 // TODO(sync): We should be able to build the actual enumset's internal
348 // bitset value here at compile time, rather than performing an iteration
349 // every time.
350 for (int i = FIRST_USER_MODEL_TYPE; i <= LAST_USER_MODEL_TYPE; ++i) {
351 set.Put(ModelTypeFromInt(i));
352 }
353 return set;
354 }
355
UserSelectableTypes()356 ModelTypeSet UserSelectableTypes() {
357 ModelTypeSet set;
358 // Although the order doesn't technically matter here, it's clearer to keep
359 // these in the same order as their definition in the ModelType enum.
360 set.Put(BOOKMARKS);
361 set.Put(PREFERENCES);
362 set.Put(PASSWORDS);
363 set.Put(AUTOFILL);
364 set.Put(THEMES);
365 set.Put(TYPED_URLS);
366 set.Put(EXTENSIONS);
367 set.Put(APPS);
368 set.Put(PROXY_TABS);
369 return set;
370 }
371
IsUserSelectableType(ModelType model_type)372 bool IsUserSelectableType(ModelType model_type) {
373 return UserSelectableTypes().Has(model_type);
374 }
375
EncryptableUserTypes()376 ModelTypeSet EncryptableUserTypes() {
377 ModelTypeSet encryptable_user_types = UserTypes();
378 // We never encrypt history delete directives.
379 encryptable_user_types.Remove(HISTORY_DELETE_DIRECTIVES);
380 // Synced notifications are not encrypted since the server must see changes.
381 encryptable_user_types.Remove(SYNCED_NOTIFICATIONS);
382 // Priority preferences are not encrypted because they might be synced before
383 // encryption is ready.
384 encryptable_user_types.Remove(PRIORITY_PREFERENCES);
385 // Managed user settings are not encrypted since they are set server-side.
386 encryptable_user_types.Remove(MANAGED_USER_SETTINGS);
387 // Managed users are not encrypted since they are managed server-side.
388 encryptable_user_types.Remove(MANAGED_USERS);
389 // Proxy types have no sync representation and are therefore not encrypted.
390 // Note however that proxy types map to one or more protocol types, which
391 // may or may not be encrypted themselves.
392 encryptable_user_types.RemoveAll(ProxyTypes());
393 return encryptable_user_types;
394 }
395
PriorityUserTypes()396 ModelTypeSet PriorityUserTypes() {
397 return ModelTypeSet(PRIORITY_PREFERENCES);
398 }
399
ControlTypes()400 ModelTypeSet ControlTypes() {
401 ModelTypeSet set;
402 // TODO(sync): We should be able to build the actual enumset's internal
403 // bitset value here at compile time, rather than performing an iteration
404 // every time.
405 for (int i = FIRST_CONTROL_MODEL_TYPE; i <= LAST_CONTROL_MODEL_TYPE; ++i) {
406 set.Put(ModelTypeFromInt(i));
407 }
408
409 return set;
410 }
411
ProxyTypes()412 ModelTypeSet ProxyTypes() {
413 ModelTypeSet set;
414 set.Put(PROXY_TABS);
415 return set;
416 }
417
IsControlType(ModelType model_type)418 bool IsControlType(ModelType model_type) {
419 return ControlTypes().Has(model_type);
420 }
421
CoreTypes()422 ModelTypeSet CoreTypes() {
423 syncer::ModelTypeSet result;
424 result.PutAll(PriorityCoreTypes());
425
426 // The following are low priority core types.
427 result.Put(SYNCED_NOTIFICATIONS);
428
429 return result;
430 }
431
PriorityCoreTypes()432 ModelTypeSet PriorityCoreTypes() {
433 syncer::ModelTypeSet result;
434 result.PutAll(ControlTypes());
435
436 // The following are non-control core types.
437 result.Put(MANAGED_USERS);
438
439 return result;
440 }
441
ModelTypeToString(ModelType model_type)442 const char* ModelTypeToString(ModelType model_type) {
443 // This is used in serialization routines as well as for displaying debug
444 // information. Do not attempt to change these string values unless you know
445 // what you're doing.
446 switch (model_type) {
447 case TOP_LEVEL_FOLDER:
448 return "Top Level Folder";
449 case UNSPECIFIED:
450 return "Unspecified";
451 case BOOKMARKS:
452 return "Bookmarks";
453 case PREFERENCES:
454 return "Preferences";
455 case PASSWORDS:
456 return "Passwords";
457 case AUTOFILL:
458 return "Autofill";
459 case THEMES:
460 return "Themes";
461 case TYPED_URLS:
462 return "Typed URLs";
463 case EXTENSIONS:
464 return "Extensions";
465 case NIGORI:
466 return "Encryption keys";
467 case SEARCH_ENGINES:
468 return "Search Engines";
469 case SESSIONS:
470 return "Sessions";
471 case APPS:
472 return "Apps";
473 case APP_LIST:
474 return "App List";
475 case AUTOFILL_PROFILE:
476 return "Autofill Profiles";
477 case APP_SETTINGS:
478 return "App settings";
479 case EXTENSION_SETTINGS:
480 return "Extension settings";
481 case APP_NOTIFICATIONS:
482 return "App Notifications";
483 case HISTORY_DELETE_DIRECTIVES:
484 return "History Delete Directives";
485 case SYNCED_NOTIFICATIONS:
486 return "Synced Notifications";
487 case DEVICE_INFO:
488 return "Device Info";
489 case EXPERIMENTS:
490 return "Experiments";
491 case PRIORITY_PREFERENCES:
492 return "Priority Preferences";
493 case DICTIONARY:
494 return "Dictionary";
495 case FAVICON_IMAGES:
496 return "Favicon Images";
497 case FAVICON_TRACKING:
498 return "Favicon Tracking";
499 case MANAGED_USER_SETTINGS:
500 return "Managed User Settings";
501 case MANAGED_USERS:
502 return "Managed Users";
503 case ARTICLES:
504 return "Articles";
505 case PROXY_TABS:
506 return "Tabs";
507 default:
508 break;
509 }
510 NOTREACHED() << "No known extension for model type.";
511 return "INVALID";
512 }
513
514 // The normal rules about histograms apply here. Always append to the bottom of
515 // the list, and be careful to not reuse integer values that have already been
516 // assigned. Don't forget to update histograms.xml when you make changes to
517 // this list.
ModelTypeToHistogramInt(ModelType model_type)518 int ModelTypeToHistogramInt(ModelType model_type) {
519 switch (model_type) {
520 case UNSPECIFIED:
521 return 0;
522 case TOP_LEVEL_FOLDER:
523 return 1;
524 case BOOKMARKS:
525 return 2;
526 case PREFERENCES:
527 return 3;
528 case PASSWORDS:
529 return 4;
530 case AUTOFILL_PROFILE:
531 return 5;
532 case AUTOFILL:
533 return 6;
534 case THEMES:
535 return 7;
536 case TYPED_URLS:
537 return 8;
538 case EXTENSIONS:
539 return 9;
540 case SEARCH_ENGINES:
541 return 10;
542 case SESSIONS:
543 return 11;
544 case APPS:
545 return 12;
546 case APP_SETTINGS:
547 return 13;
548 case EXTENSION_SETTINGS:
549 return 14;
550 case APP_NOTIFICATIONS:
551 return 15;
552 case HISTORY_DELETE_DIRECTIVES:
553 return 16;
554 case NIGORI:
555 return 17;
556 case DEVICE_INFO:
557 return 18;
558 case EXPERIMENTS:
559 return 19;
560 case SYNCED_NOTIFICATIONS:
561 return 20;
562 case PRIORITY_PREFERENCES:
563 return 21;
564 case DICTIONARY:
565 return 22;
566 case FAVICON_IMAGES:
567 return 23;
568 case FAVICON_TRACKING:
569 return 24;
570 case PROXY_TABS:
571 return 25;
572 case MANAGED_USER_SETTINGS:
573 return 26;
574 case MANAGED_USERS:
575 return 27;
576 case ARTICLES:
577 return 28;
578 case APP_LIST:
579 return 29;
580 // Silence a compiler warning.
581 case MODEL_TYPE_COUNT:
582 return 0;
583 }
584 return 0;
585 }
586
ModelTypeToValue(ModelType model_type)587 base::StringValue* ModelTypeToValue(ModelType model_type) {
588 if (model_type >= FIRST_REAL_MODEL_TYPE) {
589 return new base::StringValue(ModelTypeToString(model_type));
590 } else if (model_type == TOP_LEVEL_FOLDER) {
591 return new base::StringValue("Top-level folder");
592 } else if (model_type == UNSPECIFIED) {
593 return new base::StringValue("Unspecified");
594 }
595 NOTREACHED();
596 return new base::StringValue(std::string());
597 }
598
ModelTypeFromValue(const base::Value & value)599 ModelType ModelTypeFromValue(const base::Value& value) {
600 if (value.IsType(base::Value::TYPE_STRING)) {
601 std::string result;
602 CHECK(value.GetAsString(&result));
603 return ModelTypeFromString(result);
604 } else if (value.IsType(base::Value::TYPE_INTEGER)) {
605 int result;
606 CHECK(value.GetAsInteger(&result));
607 return ModelTypeFromInt(result);
608 } else {
609 NOTREACHED() << "Unsupported value type: " << value.GetType();
610 return UNSPECIFIED;
611 }
612 }
613
ModelTypeFromString(const std::string & model_type_string)614 ModelType ModelTypeFromString(const std::string& model_type_string) {
615 if (model_type_string == "Bookmarks")
616 return BOOKMARKS;
617 else if (model_type_string == "Preferences")
618 return PREFERENCES;
619 else if (model_type_string == "Passwords")
620 return PASSWORDS;
621 else if (model_type_string == "Autofill")
622 return AUTOFILL;
623 else if (model_type_string == "Autofill Profiles")
624 return AUTOFILL_PROFILE;
625 else if (model_type_string == "Themes")
626 return THEMES;
627 else if (model_type_string == "Typed URLs")
628 return TYPED_URLS;
629 else if (model_type_string == "Extensions")
630 return EXTENSIONS;
631 else if (model_type_string == "Encryption keys")
632 return NIGORI;
633 else if (model_type_string == "Search Engines")
634 return SEARCH_ENGINES;
635 else if (model_type_string == "Sessions")
636 return SESSIONS;
637 else if (model_type_string == "Apps")
638 return APPS;
639 else if (model_type_string == "App List")
640 return APP_LIST;
641 else if (model_type_string == "App settings")
642 return APP_SETTINGS;
643 else if (model_type_string == "Extension settings")
644 return EXTENSION_SETTINGS;
645 else if (model_type_string == "App Notifications")
646 return APP_NOTIFICATIONS;
647 else if (model_type_string == "History Delete Directives")
648 return HISTORY_DELETE_DIRECTIVES;
649 else if (model_type_string == "Synced Notifications")
650 return SYNCED_NOTIFICATIONS;
651 else if (model_type_string == "Device Info")
652 return DEVICE_INFO;
653 else if (model_type_string == "Experiments")
654 return EXPERIMENTS;
655 else if (model_type_string == "Priority Preferences")
656 return PRIORITY_PREFERENCES;
657 else if (model_type_string == "Dictionary")
658 return DICTIONARY;
659 else if (model_type_string == "Favicon Images")
660 return FAVICON_IMAGES;
661 else if (model_type_string == "Favicon Tracking")
662 return FAVICON_TRACKING;
663 else if (model_type_string == "Managed User Settings")
664 return MANAGED_USER_SETTINGS;
665 else if (model_type_string == "Managed Users")
666 return MANAGED_USERS;
667 else if (model_type_string == "Articles")
668 return ARTICLES;
669 else if (model_type_string == "Tabs")
670 return PROXY_TABS;
671 else
672 NOTREACHED() << "No known model type corresponding to "
673 << model_type_string << ".";
674 return UNSPECIFIED;
675 }
676
ModelTypeSetToString(ModelTypeSet model_types)677 std::string ModelTypeSetToString(ModelTypeSet model_types) {
678 std::string result;
679 for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) {
680 if (!result.empty()) {
681 result += ", ";
682 }
683 result += ModelTypeToString(it.Get());
684 }
685 return result;
686 }
687
ModelTypeSetToValue(ModelTypeSet model_types)688 base::ListValue* ModelTypeSetToValue(ModelTypeSet model_types) {
689 base::ListValue* value = new base::ListValue();
690 for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) {
691 value->Append(new base::StringValue(ModelTypeToString(it.Get())));
692 }
693 return value;
694 }
695
ModelTypeSetFromValue(const base::ListValue & value)696 ModelTypeSet ModelTypeSetFromValue(const base::ListValue& value) {
697 ModelTypeSet result;
698 for (base::ListValue::const_iterator i = value.begin();
699 i != value.end(); ++i) {
700 result.Put(ModelTypeFromValue(**i));
701 }
702 return result;
703 }
704
705 // TODO(zea): remove all hardcoded tags in model associators and have them use
706 // this instead.
707 // NOTE: Proxy types should return empty strings (so that we don't NOTREACHED
708 // in tests when we verify they have no root node).
ModelTypeToRootTag(ModelType type)709 std::string ModelTypeToRootTag(ModelType type) {
710 switch (type) {
711 case BOOKMARKS:
712 return "google_chrome_bookmarks";
713 case PREFERENCES:
714 return "google_chrome_preferences";
715 case PASSWORDS:
716 return "google_chrome_passwords";
717 case AUTOFILL:
718 return "google_chrome_autofill";
719 case THEMES:
720 return "google_chrome_themes";
721 case TYPED_URLS:
722 return "google_chrome_typed_urls";
723 case EXTENSIONS:
724 return "google_chrome_extensions";
725 case NIGORI:
726 return "google_chrome_nigori";
727 case SEARCH_ENGINES:
728 return "google_chrome_search_engines";
729 case SESSIONS:
730 return "google_chrome_sessions";
731 case APPS:
732 return "google_chrome_apps";
733 case APP_LIST:
734 return "google_chrome_app_list";
735 case AUTOFILL_PROFILE:
736 return "google_chrome_autofill_profiles";
737 case APP_SETTINGS:
738 return "google_chrome_app_settings";
739 case EXTENSION_SETTINGS:
740 return "google_chrome_extension_settings";
741 case APP_NOTIFICATIONS:
742 return "google_chrome_app_notifications";
743 case HISTORY_DELETE_DIRECTIVES:
744 return "google_chrome_history_delete_directives";
745 case SYNCED_NOTIFICATIONS:
746 return "google_chrome_synced_notifications";
747 case DEVICE_INFO:
748 return "google_chrome_device_info";
749 case EXPERIMENTS:
750 return "google_chrome_experiments";
751 case PRIORITY_PREFERENCES:
752 return "google_chrome_priority_preferences";
753 case DICTIONARY:
754 return "google_chrome_dictionary";
755 case FAVICON_IMAGES:
756 return "google_chrome_favicon_images";
757 case FAVICON_TRACKING:
758 return "google_chrome_favicon_tracking";
759 case MANAGED_USER_SETTINGS:
760 return "google_chrome_managed_user_settings";
761 case MANAGED_USERS:
762 return "google_chrome_managed_users";
763 case ARTICLES:
764 return "google_chrome_articles";
765 case PROXY_TABS:
766 return std::string();
767 default:
768 break;
769 }
770 NOTREACHED() << "No known extension for model type.";
771 return "INVALID";
772 }
773
774 // TODO(akalin): Figure out a better way to do these mappings.
775 // Note: Do not include proxy types in this list. They should never receive
776 // or trigger notifications.
777 namespace {
778 const char kBookmarkNotificationType[] = "BOOKMARK";
779 const char kPreferenceNotificationType[] = "PREFERENCE";
780 const char kPasswordNotificationType[] = "PASSWORD";
781 const char kAutofillNotificationType[] = "AUTOFILL";
782 const char kThemeNotificationType[] = "THEME";
783 const char kTypedUrlNotificationType[] = "TYPED_URL";
784 const char kExtensionNotificationType[] = "EXTENSION";
785 const char kExtensionSettingNotificationType[] = "EXTENSION_SETTING";
786 const char kNigoriNotificationType[] = "NIGORI";
787 const char kAppSettingNotificationType[] = "APP_SETTING";
788 const char kAppNotificationType[] = "APP";
789 const char kAppListNotificationType[] = "APP_LIST";
790 const char kSearchEngineNotificationType[] = "SEARCH_ENGINE";
791 const char kSessionNotificationType[] = "SESSION";
792 const char kAutofillProfileNotificationType[] = "AUTOFILL_PROFILE";
793 const char kAppNotificationNotificationType[] = "APP_NOTIFICATION";
794 const char kHistoryDeleteDirectiveNotificationType[] =
795 "HISTORY_DELETE_DIRECTIVE";
796 const char kSyncedNotificationType[] = "SYNCED_NOTIFICATION";
797 const char kDeviceInfoNotificationType[] = "DEVICE_INFO";
798 const char kExperimentsNotificationType[] = "EXPERIMENTS";
799 const char kPriorityPreferenceNotificationType[] = "PRIORITY_PREFERENCE";
800 const char kDictionaryNotificationType[] = "DICTIONARY";
801 const char kFaviconImageNotificationType[] = "FAVICON_IMAGE";
802 const char kFaviconTrackingNotificationType[] = "FAVICON_TRACKING";
803 const char kManagedUserSettingNotificationType[] = "MANAGED_USER_SETTING";
804 const char kManagedUserNotificationType[] = "MANAGED_USER";
805 const char kArticleNotificationType[] = "ARTICLE";
806 } // namespace
807
RealModelTypeToNotificationType(ModelType model_type,std::string * notification_type)808 bool RealModelTypeToNotificationType(ModelType model_type,
809 std::string* notification_type) {
810 switch (model_type) {
811 case BOOKMARKS:
812 *notification_type = kBookmarkNotificationType;
813 return true;
814 case PREFERENCES:
815 *notification_type = kPreferenceNotificationType;
816 return true;
817 case PASSWORDS:
818 *notification_type = kPasswordNotificationType;
819 return true;
820 case AUTOFILL:
821 *notification_type = kAutofillNotificationType;
822 return true;
823 case THEMES:
824 *notification_type = kThemeNotificationType;
825 return true;
826 case TYPED_URLS:
827 *notification_type = kTypedUrlNotificationType;
828 return true;
829 case EXTENSIONS:
830 *notification_type = kExtensionNotificationType;
831 return true;
832 case NIGORI:
833 *notification_type = kNigoriNotificationType;
834 return true;
835 case APP_SETTINGS:
836 *notification_type = kAppSettingNotificationType;
837 return true;
838 case APPS:
839 *notification_type = kAppNotificationType;
840 return true;
841 case APP_LIST:
842 *notification_type = kAppListNotificationType;
843 return true;
844 case SEARCH_ENGINES:
845 *notification_type = kSearchEngineNotificationType;
846 return true;
847 case SESSIONS:
848 *notification_type = kSessionNotificationType;
849 return true;
850 case AUTOFILL_PROFILE:
851 *notification_type = kAutofillProfileNotificationType;
852 return true;
853 case EXTENSION_SETTINGS:
854 *notification_type = kExtensionSettingNotificationType;
855 return true;
856 case APP_NOTIFICATIONS:
857 *notification_type = kAppNotificationNotificationType;
858 return true;
859 case HISTORY_DELETE_DIRECTIVES:
860 *notification_type = kHistoryDeleteDirectiveNotificationType;
861 return true;
862 case SYNCED_NOTIFICATIONS:
863 *notification_type = kSyncedNotificationType;
864 return true;
865 case DEVICE_INFO:
866 *notification_type = kDeviceInfoNotificationType;
867 return true;
868 case EXPERIMENTS:
869 *notification_type = kExperimentsNotificationType;
870 return true;
871 case PRIORITY_PREFERENCES:
872 *notification_type = kPriorityPreferenceNotificationType;
873 return true;
874 case DICTIONARY:
875 *notification_type = kDictionaryNotificationType;
876 return true;
877 case FAVICON_IMAGES:
878 *notification_type = kFaviconImageNotificationType;
879 return true;
880 case FAVICON_TRACKING:
881 *notification_type = kFaviconTrackingNotificationType;
882 return true;
883 case MANAGED_USER_SETTINGS:
884 *notification_type = kManagedUserSettingNotificationType;
885 return true;
886 case MANAGED_USERS:
887 *notification_type = kManagedUserNotificationType;
888 return true;
889 case ARTICLES:
890 *notification_type = kArticleNotificationType;
891 return true;
892 default:
893 break;
894 }
895 notification_type->clear();
896 return false;
897 }
898
NotificationTypeToRealModelType(const std::string & notification_type,ModelType * model_type)899 bool NotificationTypeToRealModelType(const std::string& notification_type,
900 ModelType* model_type) {
901 if (notification_type == kBookmarkNotificationType) {
902 *model_type = BOOKMARKS;
903 return true;
904 } else if (notification_type == kPreferenceNotificationType) {
905 *model_type = PREFERENCES;
906 return true;
907 } else if (notification_type == kPasswordNotificationType) {
908 *model_type = PASSWORDS;
909 return true;
910 } else if (notification_type == kAutofillNotificationType) {
911 *model_type = AUTOFILL;
912 return true;
913 } else if (notification_type == kThemeNotificationType) {
914 *model_type = THEMES;
915 return true;
916 } else if (notification_type == kTypedUrlNotificationType) {
917 *model_type = TYPED_URLS;
918 return true;
919 } else if (notification_type == kExtensionNotificationType) {
920 *model_type = EXTENSIONS;
921 return true;
922 } else if (notification_type == kNigoriNotificationType) {
923 *model_type = NIGORI;
924 return true;
925 } else if (notification_type == kAppNotificationType) {
926 *model_type = APPS;
927 return true;
928 } else if (notification_type == kAppListNotificationType) {
929 *model_type = APP_LIST;
930 return true;
931 } else if (notification_type == kSearchEngineNotificationType) {
932 *model_type = SEARCH_ENGINES;
933 return true;
934 } else if (notification_type == kSessionNotificationType) {
935 *model_type = SESSIONS;
936 return true;
937 } else if (notification_type == kAutofillProfileNotificationType) {
938 *model_type = AUTOFILL_PROFILE;
939 return true;
940 } else if (notification_type == kAppSettingNotificationType) {
941 *model_type = APP_SETTINGS;
942 return true;
943 } else if (notification_type == kExtensionSettingNotificationType) {
944 *model_type = EXTENSION_SETTINGS;
945 return true;
946 } else if (notification_type == kAppNotificationNotificationType) {
947 *model_type = APP_NOTIFICATIONS;
948 return true;
949 } else if (notification_type == kHistoryDeleteDirectiveNotificationType) {
950 *model_type = HISTORY_DELETE_DIRECTIVES;
951 return true;
952 } else if (notification_type == kSyncedNotificationType) {
953 *model_type = SYNCED_NOTIFICATIONS;
954 return true;
955 } else if (notification_type == kDeviceInfoNotificationType) {
956 *model_type = DEVICE_INFO;
957 return true;
958 } else if (notification_type == kExperimentsNotificationType) {
959 *model_type = EXPERIMENTS;
960 return true;
961 } else if (notification_type == kPriorityPreferenceNotificationType) {
962 *model_type = PRIORITY_PREFERENCES;
963 return true;
964 } else if (notification_type == kDictionaryNotificationType) {
965 *model_type = DICTIONARY;
966 return true;
967 } else if (notification_type == kFaviconImageNotificationType) {
968 *model_type = FAVICON_IMAGES;
969 return true;
970 } else if (notification_type == kFaviconTrackingNotificationType) {
971 *model_type = FAVICON_TRACKING;
972 return true;
973 } else if (notification_type == kManagedUserSettingNotificationType) {
974 *model_type = MANAGED_USER_SETTINGS;
975 return true;
976 } else if (notification_type == kManagedUserNotificationType) {
977 *model_type = MANAGED_USERS;
978 return true;
979 } else if (notification_type == kArticleNotificationType) {
980 *model_type = ARTICLES;
981 return true;
982 }
983 *model_type = UNSPECIFIED;
984 return false;
985 }
986
IsRealDataType(ModelType model_type)987 bool IsRealDataType(ModelType model_type) {
988 return model_type >= FIRST_REAL_MODEL_TYPE && model_type < MODEL_TYPE_COUNT;
989 }
990
IsActOnceDataType(ModelType model_type)991 bool IsActOnceDataType(ModelType model_type) {
992 return model_type == HISTORY_DELETE_DIRECTIVES;
993 }
994
995 } // namespace syncer
996