Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / sync / syncable / model_type.cc
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
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
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
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
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!
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
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
330 ModelTypeSet ProtocolTypes() {
331   ModelTypeSet set = ModelTypeSet::All();
332   set.RemoveAll(ProxyTypes());
333   return set;
334 }
335
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
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
363 bool IsUserSelectableType(ModelType model_type) {
364   return UserSelectableTypes().Has(model_type);
365 }
366
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   // Device info data is not encrypted because it might be synced before
377   // encryption is ready.
378   encryptable_user_types.Remove(DEVICE_INFO);
379   // Priority preferences are not encrypted because they might be synced before
380   // encryption is ready.
381   encryptable_user_types.Remove(PRIORITY_PREFERENCES);
382   // Supervised user settings are not encrypted since they are set server-side.
383   encryptable_user_types.Remove(SUPERVISED_USER_SETTINGS);
384   // Supervised users are not encrypted since they are managed server-side.
385   encryptable_user_types.Remove(SUPERVISED_USERS);
386   // Supervised user shared settings are not encrypted since they are managed
387   // server-side and shared between manager and supervised user.
388   encryptable_user_types.Remove(SUPERVISED_USER_SHARED_SETTINGS);
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
396 ModelTypeSet PriorityUserTypes() {
397   return ModelTypeSet(DEVICE_INFO, PRIORITY_PREFERENCES);
398 }
399
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
412 ModelTypeSet ProxyTypes() {
413   ModelTypeSet set;
414   set.Put(PROXY_TABS);
415   return set;
416 }
417
418 bool IsControlType(ModelType model_type) {
419   return ControlTypes().Has(model_type);
420 }
421
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   result.Put(SYNCED_NOTIFICATION_APP_INFO);
429   result.Put(SUPERVISED_USER_SHARED_SETTINGS);
430
431   return result;
432 }
433
434 ModelTypeSet PriorityCoreTypes() {
435   syncer::ModelTypeSet result;
436   result.PutAll(ControlTypes());
437
438   // The following are non-control core types.
439   result.Put(SUPERVISED_USERS);
440   result.Put(SUPERVISED_USER_SETTINGS);
441
442   return result;
443 }
444
445 ModelTypeSet BackupTypes() {
446   ModelTypeSet result;
447   result.Put(BOOKMARKS);
448   result.Put(PREFERENCES);
449   result.Put(THEMES);
450   result.Put(EXTENSIONS);
451   result.Put(SEARCH_ENGINES);
452   result.Put(APPS);
453   result.Put(APP_LIST);
454   result.Put(APP_SETTINGS);
455   result.Put(EXTENSION_SETTINGS);
456   result.Put(PRIORITY_PREFERENCES);
457   return result;
458 }
459
460 const char* ModelTypeToString(ModelType model_type) {
461   // This is used in serialization routines as well as for displaying debug
462   // information.  Do not attempt to change these string values unless you know
463   // what you're doing.
464   switch (model_type) {
465     case TOP_LEVEL_FOLDER:
466       return "Top Level Folder";
467     case UNSPECIFIED:
468       return "Unspecified";
469     case BOOKMARKS:
470       return "Bookmarks";
471     case PREFERENCES:
472       return "Preferences";
473     case PASSWORDS:
474       return "Passwords";
475     case AUTOFILL:
476       return "Autofill";
477     case THEMES:
478       return "Themes";
479     case TYPED_URLS:
480       return "Typed URLs";
481     case EXTENSIONS:
482       return "Extensions";
483     case NIGORI:
484       return "Encryption keys";
485     case SEARCH_ENGINES:
486       return "Search Engines";
487     case SESSIONS:
488       return "Sessions";
489     case APPS:
490       return "Apps";
491     case APP_LIST:
492       return "App List";
493     case AUTOFILL_PROFILE:
494       return "Autofill Profiles";
495     case APP_SETTINGS:
496       return "App settings";
497     case EXTENSION_SETTINGS:
498       return "Extension settings";
499     case APP_NOTIFICATIONS:
500       return "App Notifications";
501     case HISTORY_DELETE_DIRECTIVES:
502       return "History Delete Directives";
503     case SYNCED_NOTIFICATIONS:
504       return "Synced Notifications";
505     case SYNCED_NOTIFICATION_APP_INFO:
506       return "Synced Notification App Info";
507     case DEVICE_INFO:
508       return "Device Info";
509     case EXPERIMENTS:
510       return "Experiments";
511     case PRIORITY_PREFERENCES:
512       return "Priority Preferences";
513     case DICTIONARY:
514       return "Dictionary";
515     case FAVICON_IMAGES:
516       return "Favicon Images";
517     case FAVICON_TRACKING:
518       return "Favicon Tracking";
519     case SUPERVISED_USER_SETTINGS:
520       return "Managed User Settings";
521     case SUPERVISED_USERS:
522       return "Managed Users";
523     case SUPERVISED_USER_SHARED_SETTINGS:
524       return "Managed User Shared Settings";
525     case ARTICLES:
526       return "Articles";
527     case PROXY_TABS:
528       return "Tabs";
529     default:
530       break;
531   }
532   NOTREACHED() << "No known extension for model type.";
533   return "INVALID";
534 }
535
536 // The normal rules about histograms apply here.  Always append to the bottom of
537 // the list, and be careful to not reuse integer values that have already been
538 // assigned.  Don't forget to update histograms.xml when you make changes to
539 // this list.
540 int ModelTypeToHistogramInt(ModelType model_type) {
541   switch (model_type) {
542     case UNSPECIFIED:
543       return 0;
544     case TOP_LEVEL_FOLDER:
545       return 1;
546     case BOOKMARKS:
547       return 2;
548     case PREFERENCES:
549       return 3;
550     case PASSWORDS:
551       return 4;
552     case AUTOFILL_PROFILE:
553       return 5;
554     case AUTOFILL:
555       return 6;
556     case THEMES:
557       return 7;
558     case TYPED_URLS:
559       return 8;
560     case EXTENSIONS:
561       return 9;
562     case SEARCH_ENGINES:
563       return 10;
564     case SESSIONS:
565       return 11;
566     case APPS:
567       return 12;
568     case APP_SETTINGS:
569       return 13;
570     case EXTENSION_SETTINGS:
571       return 14;
572     case APP_NOTIFICATIONS:
573       return 15;
574     case HISTORY_DELETE_DIRECTIVES:
575       return 16;
576     case NIGORI:
577       return 17;
578     case DEVICE_INFO:
579       return 18;
580     case EXPERIMENTS:
581       return 19;
582     case SYNCED_NOTIFICATIONS:
583       return 20;
584     case PRIORITY_PREFERENCES:
585       return 21;
586     case DICTIONARY:
587       return 22;
588     case FAVICON_IMAGES:
589       return 23;
590     case FAVICON_TRACKING:
591       return 24;
592     case PROXY_TABS:
593       return 25;
594     case SUPERVISED_USER_SETTINGS:
595       return 26;
596     case SUPERVISED_USERS:
597       return 27;
598     case ARTICLES:
599       return 28;
600     case APP_LIST:
601       return 29;
602     case SUPERVISED_USER_SHARED_SETTINGS:
603       return 30;
604     case SYNCED_NOTIFICATION_APP_INFO:
605       return 31;
606     // Silence a compiler warning.
607     case MODEL_TYPE_COUNT:
608       return 0;
609   }
610   return 0;
611 }
612
613 base::StringValue* ModelTypeToValue(ModelType model_type) {
614   if (model_type >= FIRST_REAL_MODEL_TYPE) {
615     return new base::StringValue(ModelTypeToString(model_type));
616   } else if (model_type == TOP_LEVEL_FOLDER) {
617     return new base::StringValue("Top-level folder");
618   } else if (model_type == UNSPECIFIED) {
619     return new base::StringValue("Unspecified");
620   }
621   NOTREACHED();
622   return new base::StringValue(std::string());
623 }
624
625 ModelType ModelTypeFromValue(const base::Value& value) {
626   if (value.IsType(base::Value::TYPE_STRING)) {
627     std::string result;
628     CHECK(value.GetAsString(&result));
629     return ModelTypeFromString(result);
630   } else if (value.IsType(base::Value::TYPE_INTEGER)) {
631     int result;
632     CHECK(value.GetAsInteger(&result));
633     return ModelTypeFromInt(result);
634   } else {
635     NOTREACHED() << "Unsupported value type: " << value.GetType();
636     return UNSPECIFIED;
637   }
638 }
639
640 ModelType ModelTypeFromString(const std::string& model_type_string) {
641   if (model_type_string == "Bookmarks")
642     return BOOKMARKS;
643   else if (model_type_string == "Preferences")
644     return PREFERENCES;
645   else if (model_type_string == "Passwords")
646     return PASSWORDS;
647   else if (model_type_string == "Autofill")
648     return AUTOFILL;
649   else if (model_type_string == "Autofill Profiles")
650     return AUTOFILL_PROFILE;
651   else if (model_type_string == "Themes")
652     return THEMES;
653   else if (model_type_string == "Typed URLs")
654     return TYPED_URLS;
655   else if (model_type_string == "Extensions")
656     return EXTENSIONS;
657   else if (model_type_string == "Encryption keys")
658     return NIGORI;
659   else if (model_type_string == "Search Engines")
660     return SEARCH_ENGINES;
661   else if (model_type_string == "Sessions")
662     return SESSIONS;
663   else if (model_type_string == "Apps")
664     return APPS;
665   else if (model_type_string == "App List")
666     return APP_LIST;
667   else if (model_type_string == "App settings")
668     return APP_SETTINGS;
669   else if (model_type_string == "Extension settings")
670     return EXTENSION_SETTINGS;
671   else if (model_type_string == "App Notifications")
672     return APP_NOTIFICATIONS;
673   else if (model_type_string == "History Delete Directives")
674     return HISTORY_DELETE_DIRECTIVES;
675   else if (model_type_string == "Synced Notifications")
676     return SYNCED_NOTIFICATIONS;
677   else if (model_type_string == "Synced Notification App Info")
678     return SYNCED_NOTIFICATION_APP_INFO;
679   else if (model_type_string == "Device Info")
680     return DEVICE_INFO;
681   else if (model_type_string == "Experiments")
682     return EXPERIMENTS;
683   else if (model_type_string == "Priority Preferences")
684     return PRIORITY_PREFERENCES;
685   else if (model_type_string == "Dictionary")
686     return DICTIONARY;
687   else if (model_type_string == "Favicon Images")
688     return FAVICON_IMAGES;
689   else if (model_type_string == "Favicon Tracking")
690     return FAVICON_TRACKING;
691   else if (model_type_string == "Managed User Settings")
692     return SUPERVISED_USER_SETTINGS;
693   else if (model_type_string == "Managed Users")
694     return SUPERVISED_USERS;
695   else if (model_type_string == "Managed User Shared Settings")
696     return SUPERVISED_USER_SHARED_SETTINGS;
697   else if (model_type_string == "Articles")
698     return ARTICLES;
699   else if (model_type_string == "Tabs")
700     return PROXY_TABS;
701   else
702     NOTREACHED() << "No known model type corresponding to "
703                  << model_type_string << ".";
704   return UNSPECIFIED;
705 }
706
707 std::string ModelTypeSetToString(ModelTypeSet model_types) {
708   std::string result;
709   for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) {
710     if (!result.empty()) {
711       result += ", ";
712     }
713     result += ModelTypeToString(it.Get());
714   }
715   return result;
716 }
717
718 ModelTypeSet ModelTypeSetFromString(const std::string& model_types_string) {
719   std::string working_copy = model_types_string;
720   ModelTypeSet model_types;
721   while (!working_copy.empty()) {
722     // Remove any leading spaces.
723     working_copy = working_copy.substr(working_copy.find_first_not_of(' '));
724     if (working_copy.empty())
725       break;
726     std::string type_str;
727     size_t end = working_copy.find(',');
728     if (end == std::string::npos) {
729       end = working_copy.length() - 1;
730       type_str = working_copy;
731     } else {
732       type_str = working_copy.substr(0, end);
733     }
734     syncer::ModelType type = ModelTypeFromString(type_str);
735     if (IsRealDataType(type))
736       model_types.Put(type);
737     working_copy = working_copy.substr(end + 1);
738   }
739   return model_types;
740 }
741
742 base::ListValue* ModelTypeSetToValue(ModelTypeSet model_types) {
743   base::ListValue* value = new base::ListValue();
744   for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) {
745     value->Append(new base::StringValue(ModelTypeToString(it.Get())));
746   }
747   return value;
748 }
749
750 ModelTypeSet ModelTypeSetFromValue(const base::ListValue& value) {
751   ModelTypeSet result;
752   for (base::ListValue::const_iterator i = value.begin();
753        i != value.end(); ++i) {
754     result.Put(ModelTypeFromValue(**i));
755   }
756   return result;
757 }
758
759 // TODO(zea): remove all hardcoded tags in model associators and have them use
760 // this instead.
761 // NOTE: Proxy types should return empty strings (so that we don't NOTREACHED
762 // in tests when we verify they have no root node).
763 std::string ModelTypeToRootTag(ModelType type) {
764   switch (type) {
765     case BOOKMARKS:
766       return "google_chrome_bookmarks";
767     case PREFERENCES:
768       return "google_chrome_preferences";
769     case PASSWORDS:
770       return "google_chrome_passwords";
771     case AUTOFILL:
772       return "google_chrome_autofill";
773     case THEMES:
774       return "google_chrome_themes";
775     case TYPED_URLS:
776       return "google_chrome_typed_urls";
777     case EXTENSIONS:
778       return "google_chrome_extensions";
779     case NIGORI:
780       return "google_chrome_nigori";
781     case SEARCH_ENGINES:
782       return "google_chrome_search_engines";
783     case SESSIONS:
784       return "google_chrome_sessions";
785     case APPS:
786       return "google_chrome_apps";
787     case APP_LIST:
788       return "google_chrome_app_list";
789     case AUTOFILL_PROFILE:
790       return "google_chrome_autofill_profiles";
791     case APP_SETTINGS:
792       return "google_chrome_app_settings";
793     case EXTENSION_SETTINGS:
794       return "google_chrome_extension_settings";
795     case APP_NOTIFICATIONS:
796       return "google_chrome_app_notifications";
797     case HISTORY_DELETE_DIRECTIVES:
798       return "google_chrome_history_delete_directives";
799     case SYNCED_NOTIFICATIONS:
800       return "google_chrome_synced_notifications";
801     case SYNCED_NOTIFICATION_APP_INFO:
802       return "google_chrome_synced_notification_app_info";
803     case DEVICE_INFO:
804       return "google_chrome_device_info";
805     case EXPERIMENTS:
806       return "google_chrome_experiments";
807     case PRIORITY_PREFERENCES:
808       return "google_chrome_priority_preferences";
809     case DICTIONARY:
810       return "google_chrome_dictionary";
811     case FAVICON_IMAGES:
812       return "google_chrome_favicon_images";
813     case FAVICON_TRACKING:
814       return "google_chrome_favicon_tracking";
815     case SUPERVISED_USER_SETTINGS:
816       return "google_chrome_managed_user_settings";
817     case SUPERVISED_USERS:
818       return "google_chrome_managed_users";
819     case SUPERVISED_USER_SHARED_SETTINGS:
820       return "google_chrome_managed_user_shared_settings";
821     case ARTICLES:
822       return "google_chrome_articles";
823     case PROXY_TABS:
824       return std::string();
825     default:
826       break;
827   }
828   NOTREACHED() << "No known extension for model type.";
829   return "INVALID";
830 }
831
832 // TODO(akalin): Figure out a better way to do these mappings.
833 // Note: Do not include proxy types in this list. They should never receive
834 // or trigger notifications.
835 namespace {
836 const char kBookmarkNotificationType[] = "BOOKMARK";
837 const char kPreferenceNotificationType[] = "PREFERENCE";
838 const char kPasswordNotificationType[] = "PASSWORD";
839 const char kAutofillNotificationType[] = "AUTOFILL";
840 const char kThemeNotificationType[] = "THEME";
841 const char kTypedUrlNotificationType[] = "TYPED_URL";
842 const char kExtensionNotificationType[] = "EXTENSION";
843 const char kExtensionSettingNotificationType[] = "EXTENSION_SETTING";
844 const char kNigoriNotificationType[] = "NIGORI";
845 const char kAppSettingNotificationType[] = "APP_SETTING";
846 const char kAppNotificationType[] = "APP";
847 const char kAppListNotificationType[] = "APP_LIST";
848 const char kSearchEngineNotificationType[] = "SEARCH_ENGINE";
849 const char kSessionNotificationType[] = "SESSION";
850 const char kAutofillProfileNotificationType[] = "AUTOFILL_PROFILE";
851 const char kAppNotificationNotificationType[] = "APP_NOTIFICATION";
852 const char kHistoryDeleteDirectiveNotificationType[] =
853     "HISTORY_DELETE_DIRECTIVE";
854 const char kSyncedNotificationType[] = "SYNCED_NOTIFICATION";
855 const char kSyncedNotificationAppInfoType[] = "SYNCED_NOTIFICATION_APP_INFO";
856 const char kDeviceInfoNotificationType[] = "DEVICE_INFO";
857 const char kExperimentsNotificationType[] = "EXPERIMENTS";
858 const char kPriorityPreferenceNotificationType[] = "PRIORITY_PREFERENCE";
859 const char kDictionaryNotificationType[] = "DICTIONARY";
860 const char kFaviconImageNotificationType[] = "FAVICON_IMAGE";
861 const char kFaviconTrackingNotificationType[] = "FAVICON_TRACKING";
862 const char kSupervisedUserSettingNotificationType[] = "MANAGED_USER_SETTING";
863 const char kSupervisedUserNotificationType[] = "MANAGED_USER";
864 const char kSupervisedUserSharedSettingNotificationType[] =
865     "MANAGED_USER_SHARED_SETTING";
866 const char kArticleNotificationType[] = "ARTICLE";
867 }  // namespace
868
869 bool RealModelTypeToNotificationType(ModelType model_type,
870                                      std::string* notification_type) {
871   switch (model_type) {
872     case BOOKMARKS:
873       *notification_type = kBookmarkNotificationType;
874       return true;
875     case PREFERENCES:
876       *notification_type = kPreferenceNotificationType;
877       return true;
878     case PASSWORDS:
879       *notification_type = kPasswordNotificationType;
880       return true;
881     case AUTOFILL:
882       *notification_type = kAutofillNotificationType;
883       return true;
884     case THEMES:
885       *notification_type = kThemeNotificationType;
886       return true;
887     case TYPED_URLS:
888       *notification_type = kTypedUrlNotificationType;
889       return true;
890     case EXTENSIONS:
891       *notification_type = kExtensionNotificationType;
892       return true;
893     case NIGORI:
894       *notification_type = kNigoriNotificationType;
895       return true;
896     case APP_SETTINGS:
897       *notification_type = kAppSettingNotificationType;
898       return true;
899     case APPS:
900       *notification_type = kAppNotificationType;
901       return true;
902     case APP_LIST:
903       *notification_type = kAppListNotificationType;
904       return true;
905     case SEARCH_ENGINES:
906       *notification_type = kSearchEngineNotificationType;
907       return true;
908     case SESSIONS:
909       *notification_type = kSessionNotificationType;
910       return true;
911     case AUTOFILL_PROFILE:
912       *notification_type = kAutofillProfileNotificationType;
913       return true;
914     case EXTENSION_SETTINGS:
915       *notification_type = kExtensionSettingNotificationType;
916       return true;
917     case APP_NOTIFICATIONS:
918       *notification_type = kAppNotificationNotificationType;
919       return true;
920     case HISTORY_DELETE_DIRECTIVES:
921       *notification_type = kHistoryDeleteDirectiveNotificationType;
922       return true;
923     case SYNCED_NOTIFICATIONS:
924       *notification_type = kSyncedNotificationType;
925       return true;
926     case SYNCED_NOTIFICATION_APP_INFO:
927       *notification_type = kSyncedNotificationAppInfoType;
928       return true;
929     case DEVICE_INFO:
930       *notification_type = kDeviceInfoNotificationType;
931       return true;
932     case EXPERIMENTS:
933       *notification_type = kExperimentsNotificationType;
934       return true;
935     case PRIORITY_PREFERENCES:
936       *notification_type = kPriorityPreferenceNotificationType;
937       return true;
938     case DICTIONARY:
939       *notification_type = kDictionaryNotificationType;
940       return true;
941     case FAVICON_IMAGES:
942       *notification_type = kFaviconImageNotificationType;
943       return true;
944     case FAVICON_TRACKING:
945       *notification_type = kFaviconTrackingNotificationType;
946       return true;
947     case SUPERVISED_USER_SETTINGS:
948       *notification_type = kSupervisedUserSettingNotificationType;
949       return true;
950     case SUPERVISED_USERS:
951       *notification_type = kSupervisedUserNotificationType;
952       return true;
953     case SUPERVISED_USER_SHARED_SETTINGS:
954       *notification_type = kSupervisedUserSharedSettingNotificationType;
955       return true;
956     case ARTICLES:
957       *notification_type = kArticleNotificationType;
958       return true;
959     default:
960       break;
961   }
962   notification_type->clear();
963   return false;
964 }
965
966 bool NotificationTypeToRealModelType(const std::string& notification_type,
967                                      ModelType* model_type) {
968   if (notification_type == kBookmarkNotificationType) {
969     *model_type = BOOKMARKS;
970     return true;
971   } else if (notification_type == kPreferenceNotificationType) {
972     *model_type = PREFERENCES;
973     return true;
974   } else if (notification_type == kPasswordNotificationType) {
975     *model_type = PASSWORDS;
976     return true;
977   } else if (notification_type == kAutofillNotificationType) {
978     *model_type = AUTOFILL;
979     return true;
980   } else if (notification_type == kThemeNotificationType) {
981     *model_type = THEMES;
982     return true;
983   } else if (notification_type == kTypedUrlNotificationType) {
984     *model_type = TYPED_URLS;
985     return true;
986   } else if (notification_type == kExtensionNotificationType) {
987     *model_type = EXTENSIONS;
988     return true;
989   } else if (notification_type == kNigoriNotificationType) {
990     *model_type = NIGORI;
991     return true;
992   } else if (notification_type == kAppNotificationType) {
993     *model_type = APPS;
994     return true;
995   } else if (notification_type == kAppListNotificationType) {
996     *model_type = APP_LIST;
997     return true;
998   } else if (notification_type == kSearchEngineNotificationType) {
999     *model_type = SEARCH_ENGINES;
1000     return true;
1001   } else if (notification_type == kSessionNotificationType) {
1002     *model_type = SESSIONS;
1003     return true;
1004   } else if (notification_type == kAutofillProfileNotificationType) {
1005     *model_type = AUTOFILL_PROFILE;
1006     return true;
1007   } else if (notification_type == kAppSettingNotificationType) {
1008     *model_type = APP_SETTINGS;
1009     return true;
1010   } else if (notification_type == kExtensionSettingNotificationType) {
1011     *model_type = EXTENSION_SETTINGS;
1012     return true;
1013   } else if (notification_type == kAppNotificationNotificationType) {
1014     *model_type = APP_NOTIFICATIONS;
1015     return true;
1016   } else if (notification_type == kHistoryDeleteDirectiveNotificationType) {
1017     *model_type = HISTORY_DELETE_DIRECTIVES;
1018     return true;
1019   } else if (notification_type == kSyncedNotificationType) {
1020     *model_type = SYNCED_NOTIFICATIONS;
1021     return true;
1022   } else if (notification_type == kSyncedNotificationAppInfoType) {
1023     *model_type = SYNCED_NOTIFICATION_APP_INFO;
1024     return true;
1025   } else if (notification_type == kDeviceInfoNotificationType) {
1026     *model_type = DEVICE_INFO;
1027     return true;
1028   } else if (notification_type == kExperimentsNotificationType) {
1029     *model_type = EXPERIMENTS;
1030     return true;
1031   } else if (notification_type == kPriorityPreferenceNotificationType) {
1032     *model_type = PRIORITY_PREFERENCES;
1033     return true;
1034   } else if (notification_type == kDictionaryNotificationType) {
1035     *model_type = DICTIONARY;
1036     return true;
1037   } else if (notification_type == kFaviconImageNotificationType) {
1038     *model_type = FAVICON_IMAGES;
1039     return true;
1040   } else if (notification_type == kFaviconTrackingNotificationType) {
1041     *model_type = FAVICON_TRACKING;
1042     return true;
1043   } else if (notification_type == kSupervisedUserSettingNotificationType) {
1044     *model_type = SUPERVISED_USER_SETTINGS;
1045     return true;
1046   } else if (notification_type == kSupervisedUserNotificationType) {
1047     *model_type = SUPERVISED_USERS;
1048     return true;
1049   } else if (notification_type ==
1050       kSupervisedUserSharedSettingNotificationType) {
1051     *model_type = SUPERVISED_USER_SHARED_SETTINGS;
1052     return true;
1053   } else if (notification_type == kArticleNotificationType) {
1054     *model_type = ARTICLES;
1055     return true;
1056   }
1057   *model_type = UNSPECIFIED;
1058   return false;
1059 }
1060
1061 bool IsRealDataType(ModelType model_type) {
1062   return model_type >= FIRST_REAL_MODEL_TYPE && model_type < MODEL_TYPE_COUNT;
1063 }
1064
1065 bool IsProxyType(ModelType model_type) {
1066   return model_type >= FIRST_PROXY_TYPE && model_type <= LAST_PROXY_TYPE;
1067 }
1068
1069 bool IsActOnceDataType(ModelType model_type) {
1070   return model_type == HISTORY_DELETE_DIRECTIVES;
1071 }
1072
1073 }  // namespace syncer