1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "sync/internal_api/public/base/model_type.h" 6 7 #include "base/strings/string_split.h" 8 #include "base/values.h" 9 #include "sync/protocol/app_notification_specifics.pb.h" 10 #include "sync/protocol/app_setting_specifics.pb.h" 11 #include "sync/protocol/app_specifics.pb.h" 12 #include "sync/protocol/autofill_specifics.pb.h" 13 #include "sync/protocol/bookmark_specifics.pb.h" 14 #include "sync/protocol/extension_setting_specifics.pb.h" 15 #include "sync/protocol/extension_specifics.pb.h" 16 #include "sync/protocol/nigori_specifics.pb.h" 17 #include "sync/protocol/password_specifics.pb.h" 18 #include "sync/protocol/preference_specifics.pb.h" 19 #include "sync/protocol/search_engine_specifics.pb.h" 20 #include "sync/protocol/session_specifics.pb.h" 21 #include "sync/protocol/sync.pb.h" 22 #include "sync/protocol/theme_specifics.pb.h" 23 #include "sync/protocol/typed_url_specifics.pb.h" 24 #include "sync/syncable/syncable_proto_util.h" 25 26 namespace syncer { 27 28 void AddDefaultFieldValue(ModelType datatype, 29 sync_pb::EntitySpecifics* specifics) { 30 if (!ProtocolTypes().Has(datatype)) { 31 NOTREACHED() << "Only protocol types have field values."; 32 return; 33 } 34 switch (datatype) { 35 case BOOKMARKS: 36 specifics->mutable_bookmark(); 37 break; 38 case PASSWORDS: 39 specifics->mutable_password(); 40 break; 41 case PREFERENCES: 42 specifics->mutable_preference(); 43 break; 44 case AUTOFILL: 45 specifics->mutable_autofill(); 46 break; 47 case AUTOFILL_PROFILE: 48 specifics->mutable_autofill_profile(); 49 break; 50 case THEMES: 51 specifics->mutable_theme(); 52 break; 53 case TYPED_URLS: 54 specifics->mutable_typed_url(); 55 break; 56 case EXTENSIONS: 57 specifics->mutable_extension(); 58 break; 59 case NIGORI: 60 specifics->mutable_nigori(); 61 break; 62 case SEARCH_ENGINES: 63 specifics->mutable_search_engine(); 64 break; 65 case SESSIONS: 66 specifics->mutable_session(); 67 break; 68 case APPS: 69 specifics->mutable_app(); 70 break; 71 case APP_LIST: 72 specifics->mutable_app_list(); 73 break; 74 case APP_SETTINGS: 75 specifics->mutable_app_setting(); 76 break; 77 case EXTENSION_SETTINGS: 78 specifics->mutable_extension_setting(); 79 break; 80 case APP_NOTIFICATIONS: 81 specifics->mutable_app_notification(); 82 break; 83 case HISTORY_DELETE_DIRECTIVES: 84 specifics->mutable_history_delete_directive(); 85 break; 86 case SYNCED_NOTIFICATIONS: 87 specifics->mutable_synced_notification(); 88 break; 89 case 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 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 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 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! 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 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 339 ModelTypeSet ProtocolTypes() { 340 ModelTypeSet set = ModelTypeSet::All(); 341 set.RemoveAll(ProxyTypes()); 342 return set; 343 } 344 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 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 372 bool IsUserSelectableType(ModelType model_type) { 373 return UserSelectableTypes().Has(model_type); 374 } 375 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 396 ModelTypeSet PriorityUserTypes() { 397 return ModelTypeSet(PRIORITY_PREFERENCES); 398 } 399 400 ModelTypeSet ControlTypes() { 401 ModelTypeSet set; 402 // TODO(sync): We should be able to build the actual enumset's internal 403 // bitset value here at compile time, rather than performing an iteration 404 // every time. 405 for (int i = FIRST_CONTROL_MODEL_TYPE; i <= LAST_CONTROL_MODEL_TYPE; ++i) { 406 set.Put(ModelTypeFromInt(i)); 407 } 408 409 return set; 410 } 411 412 ModelTypeSet ProxyTypes() { 413 ModelTypeSet set; 414 set.Put(PROXY_TABS); 415 return set; 416 } 417 418 bool IsControlType(ModelType model_type) { 419 return ControlTypes().Has(model_type); 420 } 421 422 ModelTypeSet CoreTypes() { 423 syncer::ModelTypeSet result; 424 result.PutAll(PriorityCoreTypes()); 425 426 // The following are low priority core types. 427 result.Put(SYNCED_NOTIFICATIONS); 428 429 return result; 430 } 431 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 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. 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 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 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 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 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 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 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). 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 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 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 987 bool IsRealDataType(ModelType model_type) { 988 return model_type >= FIRST_REAL_MODEL_TYPE && model_type < MODEL_TYPE_COUNT; 989 } 990 991 bool IsActOnceDataType(ModelType model_type) { 992 return model_type == HISTORY_DELETE_DIRECTIVES; 993 } 994 995 } // namespace syncer 996