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