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