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