• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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