1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "sync/internal_api/public/base/model_type.h" 6 7 #include "base/strings/string_split.h" 8 #include "base/values.h" 9 #include "sync/protocol/app_notification_specifics.pb.h" 10 #include "sync/protocol/app_setting_specifics.pb.h" 11 #include "sync/protocol/app_specifics.pb.h" 12 #include "sync/protocol/autofill_specifics.pb.h" 13 #include "sync/protocol/bookmark_specifics.pb.h" 14 #include "sync/protocol/extension_setting_specifics.pb.h" 15 #include "sync/protocol/extension_specifics.pb.h" 16 #include "sync/protocol/nigori_specifics.pb.h" 17 #include "sync/protocol/password_specifics.pb.h" 18 #include "sync/protocol/preference_specifics.pb.h" 19 #include "sync/protocol/search_engine_specifics.pb.h" 20 #include "sync/protocol/session_specifics.pb.h" 21 #include "sync/protocol/sync.pb.h" 22 #include "sync/protocol/theme_specifics.pb.h" 23 #include "sync/protocol/typed_url_specifics.pb.h" 24 #include "sync/syncable/syncable_proto_util.h" 25 26 namespace syncer { 27 28 void AddDefaultFieldValue(ModelType datatype, 29 sync_pb::EntitySpecifics* specifics) { 30 if (!ProtocolTypes().Has(datatype)) { 31 NOTREACHED() << "Only protocol types have field values."; 32 return; 33 } 34 switch (datatype) { 35 case BOOKMARKS: 36 specifics->mutable_bookmark(); 37 break; 38 case PASSWORDS: 39 specifics->mutable_password(); 40 break; 41 case PREFERENCES: 42 specifics->mutable_preference(); 43 break; 44 case AUTOFILL: 45 specifics->mutable_autofill(); 46 break; 47 case AUTOFILL_PROFILE: 48 specifics->mutable_autofill_profile(); 49 break; 50 case THEMES: 51 specifics->mutable_theme(); 52 break; 53 case TYPED_URLS: 54 specifics->mutable_typed_url(); 55 break; 56 case EXTENSIONS: 57 specifics->mutable_extension(); 58 break; 59 case NIGORI: 60 specifics->mutable_nigori(); 61 break; 62 case SEARCH_ENGINES: 63 specifics->mutable_search_engine(); 64 break; 65 case SESSIONS: 66 specifics->mutable_session(); 67 break; 68 case APPS: 69 specifics->mutable_app(); 70 break; 71 case APP_LIST: 72 specifics->mutable_app_list(); 73 break; 74 case APP_SETTINGS: 75 specifics->mutable_app_setting(); 76 break; 77 case EXTENSION_SETTINGS: 78 specifics->mutable_extension_setting(); 79 break; 80 case APP_NOTIFICATIONS: 81 specifics->mutable_app_notification(); 82 break; 83 case HISTORY_DELETE_DIRECTIVES: 84 specifics->mutable_history_delete_directive(); 85 break; 86 case SYNCED_NOTIFICATIONS: 87 specifics->mutable_synced_notification(); 88 break; 89 case SYNCED_NOTIFICATION_APP_INFO: 90 specifics->mutable_synced_notification_app_info(); 91 break; 92 case DEVICE_INFO: 93 specifics->mutable_device_info(); 94 break; 95 case EXPERIMENTS: 96 specifics->mutable_experiments(); 97 break; 98 case PRIORITY_PREFERENCES: 99 specifics->mutable_priority_preference(); 100 break; 101 case DICTIONARY: 102 specifics->mutable_dictionary(); 103 break; 104 case FAVICON_IMAGES: 105 specifics->mutable_favicon_image(); 106 break; 107 case FAVICON_TRACKING: 108 specifics->mutable_favicon_tracking(); 109 break; 110 case SUPERVISED_USER_SETTINGS: 111 specifics->mutable_managed_user_setting(); 112 break; 113 case SUPERVISED_USERS: 114 specifics->mutable_managed_user(); 115 break; 116 case SUPERVISED_USER_SHARED_SETTINGS: 117 specifics->mutable_managed_user_shared_setting(); 118 break; 119 case ARTICLES: 120 specifics->mutable_article(); 121 break; 122 default: 123 NOTREACHED() << "No known extension for model type."; 124 } 125 } 126 127 ModelType GetModelTypeFromSpecificsFieldNumber(int field_number) { 128 ModelTypeSet protocol_types = ProtocolTypes(); 129 for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); 130 iter.Inc()) { 131 if (GetSpecificsFieldNumberFromModelType(iter.Get()) == field_number) 132 return iter.Get(); 133 } 134 return UNSPECIFIED; 135 } 136 137 int GetSpecificsFieldNumberFromModelType(ModelType model_type) { 138 DCHECK(ProtocolTypes().Has(model_type)) 139 << "Only protocol types have field values."; 140 switch (model_type) { 141 case BOOKMARKS: 142 return sync_pb::EntitySpecifics::kBookmarkFieldNumber; 143 case PASSWORDS: 144 return sync_pb::EntitySpecifics::kPasswordFieldNumber; 145 case PREFERENCES: 146 return sync_pb::EntitySpecifics::kPreferenceFieldNumber; 147 case AUTOFILL: 148 return sync_pb::EntitySpecifics::kAutofillFieldNumber; 149 case AUTOFILL_PROFILE: 150 return sync_pb::EntitySpecifics::kAutofillProfileFieldNumber; 151 case THEMES: 152 return sync_pb::EntitySpecifics::kThemeFieldNumber; 153 case TYPED_URLS: 154 return sync_pb::EntitySpecifics::kTypedUrlFieldNumber; 155 case EXTENSIONS: 156 return sync_pb::EntitySpecifics::kExtensionFieldNumber; 157 case NIGORI: 158 return sync_pb::EntitySpecifics::kNigoriFieldNumber; 159 case SEARCH_ENGINES: 160 return sync_pb::EntitySpecifics::kSearchEngineFieldNumber; 161 case SESSIONS: 162 return sync_pb::EntitySpecifics::kSessionFieldNumber; 163 case APPS: 164 return sync_pb::EntitySpecifics::kAppFieldNumber; 165 case APP_LIST: 166 return sync_pb::EntitySpecifics::kAppListFieldNumber; 167 case APP_SETTINGS: 168 return sync_pb::EntitySpecifics::kAppSettingFieldNumber; 169 case EXTENSION_SETTINGS: 170 return sync_pb::EntitySpecifics::kExtensionSettingFieldNumber; 171 case APP_NOTIFICATIONS: 172 return sync_pb::EntitySpecifics::kAppNotificationFieldNumber; 173 case HISTORY_DELETE_DIRECTIVES: 174 return sync_pb::EntitySpecifics::kHistoryDeleteDirectiveFieldNumber; 175 case SYNCED_NOTIFICATIONS: 176 return sync_pb::EntitySpecifics::kSyncedNotificationFieldNumber; 177 case SYNCED_NOTIFICATION_APP_INFO: 178 return sync_pb::EntitySpecifics::kSyncedNotificationAppInfoFieldNumber; 179 case DEVICE_INFO: 180 return sync_pb::EntitySpecifics::kDeviceInfoFieldNumber; 181 case EXPERIMENTS: 182 return sync_pb::EntitySpecifics::kExperimentsFieldNumber; 183 case PRIORITY_PREFERENCES: 184 return sync_pb::EntitySpecifics::kPriorityPreferenceFieldNumber; 185 case DICTIONARY: 186 return sync_pb::EntitySpecifics::kDictionaryFieldNumber; 187 case FAVICON_IMAGES: 188 return sync_pb::EntitySpecifics::kFaviconImageFieldNumber; 189 case FAVICON_TRACKING: 190 return sync_pb::EntitySpecifics::kFaviconTrackingFieldNumber; 191 case SUPERVISED_USER_SETTINGS: 192 return sync_pb::EntitySpecifics::kManagedUserSettingFieldNumber; 193 case SUPERVISED_USERS: 194 return sync_pb::EntitySpecifics::kManagedUserFieldNumber; 195 case SUPERVISED_USER_SHARED_SETTINGS: 196 return sync_pb::EntitySpecifics::kManagedUserSharedSettingFieldNumber; 197 case ARTICLES: 198 return sync_pb::EntitySpecifics::kArticleFieldNumber; 199 default: 200 NOTREACHED() << "No known extension for model type."; 201 return 0; 202 } 203 } 204 205 FullModelTypeSet ToFullModelTypeSet(ModelTypeSet in) { 206 FullModelTypeSet out; 207 for (ModelTypeSet::Iterator i = in.First(); i.Good(); i.Inc()) { 208 out.Put(i.Get()); 209 } 210 return out; 211 } 212 213 // Note: keep this consistent with GetModelType in entry.cc! 214 ModelType GetModelType(const sync_pb::SyncEntity& sync_entity) { 215 DCHECK(!IsRoot(sync_entity)); // Root shouldn't ever go over the wire. 216 217 // Backwards compatibility with old (pre-specifics) protocol. 218 if (sync_entity.has_bookmarkdata()) 219 return BOOKMARKS; 220 221 ModelType specifics_type = GetModelTypeFromSpecifics(sync_entity.specifics()); 222 if (specifics_type != UNSPECIFIED) 223 return specifics_type; 224 225 // Loose check for server-created top-level folders that aren't 226 // bound to a particular model type. 227 if (!sync_entity.server_defined_unique_tag().empty() && 228 IsFolder(sync_entity)) { 229 return TOP_LEVEL_FOLDER; 230 } 231 232 // This is an item of a datatype we can't understand. Maybe it's 233 // from the future? Either we mis-encoded the object, or the 234 // server sent us entries it shouldn't have. 235 NOTREACHED() << "Unknown datatype in sync proto."; 236 return UNSPECIFIED; 237 } 238 239 ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics) { 240 if (specifics.has_bookmark()) 241 return BOOKMARKS; 242 243 if (specifics.has_password()) 244 return PASSWORDS; 245 246 if (specifics.has_preference()) 247 return PREFERENCES; 248 249 if (specifics.has_autofill()) 250 return AUTOFILL; 251 252 if (specifics.has_autofill_profile()) 253 return AUTOFILL_PROFILE; 254 255 if (specifics.has_theme()) 256 return THEMES; 257 258 if (specifics.has_typed_url()) 259 return TYPED_URLS; 260 261 if (specifics.has_extension()) 262 return EXTENSIONS; 263 264 if (specifics.has_nigori()) 265 return NIGORI; 266 267 if (specifics.has_app()) 268 return APPS; 269 270 if (specifics.has_app_list()) 271 return APP_LIST; 272 273 if (specifics.has_search_engine()) 274 return SEARCH_ENGINES; 275 276 if (specifics.has_session()) 277 return SESSIONS; 278 279 if (specifics.has_app_setting()) 280 return APP_SETTINGS; 281 282 if (specifics.has_extension_setting()) 283 return EXTENSION_SETTINGS; 284 285 if (specifics.has_app_notification()) 286 return APP_NOTIFICATIONS; 287 288 if (specifics.has_history_delete_directive()) 289 return HISTORY_DELETE_DIRECTIVES; 290 291 if (specifics.has_synced_notification()) 292 return SYNCED_NOTIFICATIONS; 293 294 if (specifics.has_synced_notification_app_info()) 295 return SYNCED_NOTIFICATION_APP_INFO; 296 297 if (specifics.has_device_info()) 298 return DEVICE_INFO; 299 300 if (specifics.has_experiments()) 301 return EXPERIMENTS; 302 303 if (specifics.has_priority_preference()) 304 return PRIORITY_PREFERENCES; 305 306 if (specifics.has_dictionary()) 307 return DICTIONARY; 308 309 if (specifics.has_favicon_image()) 310 return FAVICON_IMAGES; 311 312 if (specifics.has_favicon_tracking()) 313 return FAVICON_TRACKING; 314 315 if (specifics.has_managed_user_setting()) 316 return SUPERVISED_USER_SETTINGS; 317 318 if (specifics.has_managed_user()) 319 return SUPERVISED_USERS; 320 321 if (specifics.has_managed_user_shared_setting()) 322 return SUPERVISED_USER_SHARED_SETTINGS; 323 324 if (specifics.has_article()) 325 return ARTICLES; 326 327 return UNSPECIFIED; 328 } 329 330 ModelTypeSet ProtocolTypes() { 331 ModelTypeSet set = ModelTypeSet::All(); 332 set.RemoveAll(ProxyTypes()); 333 return set; 334 } 335 336 ModelTypeSet UserTypes() { 337 ModelTypeSet set; 338 // TODO(sync): We should be able to build the actual enumset's internal 339 // bitset value here at compile time, rather than performing an iteration 340 // every time. 341 for (int i = FIRST_USER_MODEL_TYPE; i <= LAST_USER_MODEL_TYPE; ++i) { 342 set.Put(ModelTypeFromInt(i)); 343 } 344 return set; 345 } 346 347 ModelTypeSet UserSelectableTypes() { 348 ModelTypeSet set; 349 // Although the order doesn't technically matter here, it's clearer to keep 350 // these in the same order as their definition in the ModelType enum. 351 set.Put(BOOKMARKS); 352 set.Put(PREFERENCES); 353 set.Put(PASSWORDS); 354 set.Put(AUTOFILL); 355 set.Put(THEMES); 356 set.Put(TYPED_URLS); 357 set.Put(EXTENSIONS); 358 set.Put(APPS); 359 set.Put(PROXY_TABS); 360 return set; 361 } 362 363 bool IsUserSelectableType(ModelType model_type) { 364 return UserSelectableTypes().Has(model_type); 365 } 366 367 ModelTypeSet EncryptableUserTypes() { 368 ModelTypeSet encryptable_user_types = UserTypes(); 369 // We never encrypt history delete directives. 370 encryptable_user_types.Remove(HISTORY_DELETE_DIRECTIVES); 371 // Synced notifications are not encrypted since the server must see changes. 372 encryptable_user_types.Remove(SYNCED_NOTIFICATIONS); 373 // Synced Notification App Info does not have private data, so it is not 374 // encrypted. 375 encryptable_user_types.Remove(SYNCED_NOTIFICATION_APP_INFO); 376 // 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 393 ModelTypeSet PriorityUserTypes() { 394 return ModelTypeSet(PRIORITY_PREFERENCES); 395 } 396 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 409 ModelTypeSet ProxyTypes() { 410 ModelTypeSet set; 411 set.Put(PROXY_TABS); 412 return set; 413 } 414 415 bool IsControlType(ModelType model_type) { 416 return ControlTypes().Has(model_type); 417 } 418 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 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 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 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. 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 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 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 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 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 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 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 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). 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 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 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 1057 bool IsRealDataType(ModelType model_type) { 1058 return model_type >= FIRST_REAL_MODEL_TYPE && model_type < MODEL_TYPE_COUNT; 1059 } 1060 1061 bool IsProxyType(ModelType model_type) { 1062 return model_type >= FIRST_PROXY_TYPE && model_type <= LAST_PROXY_TYPE; 1063 } 1064 1065 bool IsActOnceDataType(ModelType model_type) { 1066 return model_type == HISTORY_DELETE_DIRECTIVES; 1067 } 1068 1069 } // namespace syncer 1070