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 // Device info data is not encrypted because it might be synced before 377 // encryption is ready. 378 encryptable_user_types.Remove(DEVICE_INFO); 379 // Priority preferences are not encrypted because they might be synced before 380 // encryption is ready. 381 encryptable_user_types.Remove(PRIORITY_PREFERENCES); 382 // Supervised user settings are not encrypted since they are set server-side. 383 encryptable_user_types.Remove(SUPERVISED_USER_SETTINGS); 384 // Supervised users are not encrypted since they are managed server-side. 385 encryptable_user_types.Remove(SUPERVISED_USERS); 386 // Supervised user shared settings are not encrypted since they are managed 387 // server-side and shared between manager and supervised user. 388 encryptable_user_types.Remove(SUPERVISED_USER_SHARED_SETTINGS); 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(DEVICE_INFO, 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 result.Put(SYNCED_NOTIFICATION_APP_INFO); 429 result.Put(SUPERVISED_USER_SHARED_SETTINGS); 430 431 return result; 432 } 433 434 ModelTypeSet PriorityCoreTypes() { 435 syncer::ModelTypeSet result; 436 result.PutAll(ControlTypes()); 437 438 // The following are non-control core types. 439 result.Put(SUPERVISED_USERS); 440 result.Put(SUPERVISED_USER_SETTINGS); 441 442 return result; 443 } 444 445 ModelTypeSet BackupTypes() { 446 ModelTypeSet result; 447 result.Put(BOOKMARKS); 448 result.Put(PREFERENCES); 449 result.Put(THEMES); 450 result.Put(EXTENSIONS); 451 result.Put(SEARCH_ENGINES); 452 result.Put(APPS); 453 result.Put(APP_LIST); 454 result.Put(APP_SETTINGS); 455 result.Put(EXTENSION_SETTINGS); 456 result.Put(PRIORITY_PREFERENCES); 457 return result; 458 } 459 460 const char* ModelTypeToString(ModelType model_type) { 461 // This is used in serialization routines as well as for displaying debug 462 // information. Do not attempt to change these string values unless you know 463 // what you're doing. 464 switch (model_type) { 465 case TOP_LEVEL_FOLDER: 466 return "Top Level Folder"; 467 case UNSPECIFIED: 468 return "Unspecified"; 469 case BOOKMARKS: 470 return "Bookmarks"; 471 case PREFERENCES: 472 return "Preferences"; 473 case PASSWORDS: 474 return "Passwords"; 475 case AUTOFILL: 476 return "Autofill"; 477 case THEMES: 478 return "Themes"; 479 case TYPED_URLS: 480 return "Typed URLs"; 481 case EXTENSIONS: 482 return "Extensions"; 483 case NIGORI: 484 return "Encryption keys"; 485 case SEARCH_ENGINES: 486 return "Search Engines"; 487 case SESSIONS: 488 return "Sessions"; 489 case APPS: 490 return "Apps"; 491 case APP_LIST: 492 return "App List"; 493 case AUTOFILL_PROFILE: 494 return "Autofill Profiles"; 495 case APP_SETTINGS: 496 return "App settings"; 497 case EXTENSION_SETTINGS: 498 return "Extension settings"; 499 case APP_NOTIFICATIONS: 500 return "App Notifications"; 501 case HISTORY_DELETE_DIRECTIVES: 502 return "History Delete Directives"; 503 case SYNCED_NOTIFICATIONS: 504 return "Synced Notifications"; 505 case SYNCED_NOTIFICATION_APP_INFO: 506 return "Synced Notification App Info"; 507 case DEVICE_INFO: 508 return "Device Info"; 509 case EXPERIMENTS: 510 return "Experiments"; 511 case PRIORITY_PREFERENCES: 512 return "Priority Preferences"; 513 case DICTIONARY: 514 return "Dictionary"; 515 case FAVICON_IMAGES: 516 return "Favicon Images"; 517 case FAVICON_TRACKING: 518 return "Favicon Tracking"; 519 case SUPERVISED_USER_SETTINGS: 520 return "Managed User Settings"; 521 case SUPERVISED_USERS: 522 return "Managed Users"; 523 case SUPERVISED_USER_SHARED_SETTINGS: 524 return "Managed User Shared Settings"; 525 case ARTICLES: 526 return "Articles"; 527 case PROXY_TABS: 528 return "Tabs"; 529 default: 530 break; 531 } 532 NOTREACHED() << "No known extension for model type."; 533 return "INVALID"; 534 } 535 536 // The normal rules about histograms apply here. Always append to the bottom of 537 // the list, and be careful to not reuse integer values that have already been 538 // assigned. Don't forget to update histograms.xml when you make changes to 539 // this list. 540 int ModelTypeToHistogramInt(ModelType model_type) { 541 switch (model_type) { 542 case UNSPECIFIED: 543 return 0; 544 case TOP_LEVEL_FOLDER: 545 return 1; 546 case BOOKMARKS: 547 return 2; 548 case PREFERENCES: 549 return 3; 550 case PASSWORDS: 551 return 4; 552 case AUTOFILL_PROFILE: 553 return 5; 554 case AUTOFILL: 555 return 6; 556 case THEMES: 557 return 7; 558 case TYPED_URLS: 559 return 8; 560 case EXTENSIONS: 561 return 9; 562 case SEARCH_ENGINES: 563 return 10; 564 case SESSIONS: 565 return 11; 566 case APPS: 567 return 12; 568 case APP_SETTINGS: 569 return 13; 570 case EXTENSION_SETTINGS: 571 return 14; 572 case APP_NOTIFICATIONS: 573 return 15; 574 case HISTORY_DELETE_DIRECTIVES: 575 return 16; 576 case NIGORI: 577 return 17; 578 case DEVICE_INFO: 579 return 18; 580 case EXPERIMENTS: 581 return 19; 582 case SYNCED_NOTIFICATIONS: 583 return 20; 584 case PRIORITY_PREFERENCES: 585 return 21; 586 case DICTIONARY: 587 return 22; 588 case FAVICON_IMAGES: 589 return 23; 590 case FAVICON_TRACKING: 591 return 24; 592 case PROXY_TABS: 593 return 25; 594 case SUPERVISED_USER_SETTINGS: 595 return 26; 596 case SUPERVISED_USERS: 597 return 27; 598 case ARTICLES: 599 return 28; 600 case APP_LIST: 601 return 29; 602 case SUPERVISED_USER_SHARED_SETTINGS: 603 return 30; 604 case SYNCED_NOTIFICATION_APP_INFO: 605 return 31; 606 // Silence a compiler warning. 607 case MODEL_TYPE_COUNT: 608 return 0; 609 } 610 return 0; 611 } 612 613 base::StringValue* ModelTypeToValue(ModelType model_type) { 614 if (model_type >= FIRST_REAL_MODEL_TYPE) { 615 return new base::StringValue(ModelTypeToString(model_type)); 616 } else if (model_type == TOP_LEVEL_FOLDER) { 617 return new base::StringValue("Top-level folder"); 618 } else if (model_type == UNSPECIFIED) { 619 return new base::StringValue("Unspecified"); 620 } 621 NOTREACHED(); 622 return new base::StringValue(std::string()); 623 } 624 625 ModelType ModelTypeFromValue(const base::Value& value) { 626 if (value.IsType(base::Value::TYPE_STRING)) { 627 std::string result; 628 CHECK(value.GetAsString(&result)); 629 return ModelTypeFromString(result); 630 } else if (value.IsType(base::Value::TYPE_INTEGER)) { 631 int result; 632 CHECK(value.GetAsInteger(&result)); 633 return ModelTypeFromInt(result); 634 } else { 635 NOTREACHED() << "Unsupported value type: " << value.GetType(); 636 return UNSPECIFIED; 637 } 638 } 639 640 ModelType ModelTypeFromString(const std::string& model_type_string) { 641 if (model_type_string == "Bookmarks") 642 return BOOKMARKS; 643 else if (model_type_string == "Preferences") 644 return PREFERENCES; 645 else if (model_type_string == "Passwords") 646 return PASSWORDS; 647 else if (model_type_string == "Autofill") 648 return AUTOFILL; 649 else if (model_type_string == "Autofill Profiles") 650 return AUTOFILL_PROFILE; 651 else if (model_type_string == "Themes") 652 return THEMES; 653 else if (model_type_string == "Typed URLs") 654 return TYPED_URLS; 655 else if (model_type_string == "Extensions") 656 return EXTENSIONS; 657 else if (model_type_string == "Encryption keys") 658 return NIGORI; 659 else if (model_type_string == "Search Engines") 660 return SEARCH_ENGINES; 661 else if (model_type_string == "Sessions") 662 return SESSIONS; 663 else if (model_type_string == "Apps") 664 return APPS; 665 else if (model_type_string == "App List") 666 return APP_LIST; 667 else if (model_type_string == "App settings") 668 return APP_SETTINGS; 669 else if (model_type_string == "Extension settings") 670 return EXTENSION_SETTINGS; 671 else if (model_type_string == "App Notifications") 672 return APP_NOTIFICATIONS; 673 else if (model_type_string == "History Delete Directives") 674 return HISTORY_DELETE_DIRECTIVES; 675 else if (model_type_string == "Synced Notifications") 676 return SYNCED_NOTIFICATIONS; 677 else if (model_type_string == "Synced Notification App Info") 678 return SYNCED_NOTIFICATION_APP_INFO; 679 else if (model_type_string == "Device Info") 680 return DEVICE_INFO; 681 else if (model_type_string == "Experiments") 682 return EXPERIMENTS; 683 else if (model_type_string == "Priority Preferences") 684 return PRIORITY_PREFERENCES; 685 else if (model_type_string == "Dictionary") 686 return DICTIONARY; 687 else if (model_type_string == "Favicon Images") 688 return FAVICON_IMAGES; 689 else if (model_type_string == "Favicon Tracking") 690 return FAVICON_TRACKING; 691 else if (model_type_string == "Managed User Settings") 692 return SUPERVISED_USER_SETTINGS; 693 else if (model_type_string == "Managed Users") 694 return SUPERVISED_USERS; 695 else if (model_type_string == "Managed User Shared Settings") 696 return SUPERVISED_USER_SHARED_SETTINGS; 697 else if (model_type_string == "Articles") 698 return ARTICLES; 699 else if (model_type_string == "Tabs") 700 return PROXY_TABS; 701 else 702 NOTREACHED() << "No known model type corresponding to " 703 << model_type_string << "."; 704 return UNSPECIFIED; 705 } 706 707 std::string ModelTypeSetToString(ModelTypeSet model_types) { 708 std::string result; 709 for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) { 710 if (!result.empty()) { 711 result += ", "; 712 } 713 result += ModelTypeToString(it.Get()); 714 } 715 return result; 716 } 717 718 ModelTypeSet ModelTypeSetFromString(const std::string& model_types_string) { 719 std::string working_copy = model_types_string; 720 ModelTypeSet model_types; 721 while (!working_copy.empty()) { 722 // Remove any leading spaces. 723 working_copy = working_copy.substr(working_copy.find_first_not_of(' ')); 724 if (working_copy.empty()) 725 break; 726 std::string type_str; 727 size_t end = working_copy.find(','); 728 if (end == std::string::npos) { 729 end = working_copy.length() - 1; 730 type_str = working_copy; 731 } else { 732 type_str = working_copy.substr(0, end); 733 } 734 syncer::ModelType type = ModelTypeFromString(type_str); 735 if (IsRealDataType(type)) 736 model_types.Put(type); 737 working_copy = working_copy.substr(end + 1); 738 } 739 return model_types; 740 } 741 742 base::ListValue* ModelTypeSetToValue(ModelTypeSet model_types) { 743 base::ListValue* value = new base::ListValue(); 744 for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) { 745 value->Append(new base::StringValue(ModelTypeToString(it.Get()))); 746 } 747 return value; 748 } 749 750 ModelTypeSet ModelTypeSetFromValue(const base::ListValue& value) { 751 ModelTypeSet result; 752 for (base::ListValue::const_iterator i = value.begin(); 753 i != value.end(); ++i) { 754 result.Put(ModelTypeFromValue(**i)); 755 } 756 return result; 757 } 758 759 // TODO(zea): remove all hardcoded tags in model associators and have them use 760 // this instead. 761 // NOTE: Proxy types should return empty strings (so that we don't NOTREACHED 762 // in tests when we verify they have no root node). 763 std::string ModelTypeToRootTag(ModelType type) { 764 switch (type) { 765 case BOOKMARKS: 766 return "google_chrome_bookmarks"; 767 case PREFERENCES: 768 return "google_chrome_preferences"; 769 case PASSWORDS: 770 return "google_chrome_passwords"; 771 case AUTOFILL: 772 return "google_chrome_autofill"; 773 case THEMES: 774 return "google_chrome_themes"; 775 case TYPED_URLS: 776 return "google_chrome_typed_urls"; 777 case EXTENSIONS: 778 return "google_chrome_extensions"; 779 case NIGORI: 780 return "google_chrome_nigori"; 781 case SEARCH_ENGINES: 782 return "google_chrome_search_engines"; 783 case SESSIONS: 784 return "google_chrome_sessions"; 785 case APPS: 786 return "google_chrome_apps"; 787 case APP_LIST: 788 return "google_chrome_app_list"; 789 case AUTOFILL_PROFILE: 790 return "google_chrome_autofill_profiles"; 791 case APP_SETTINGS: 792 return "google_chrome_app_settings"; 793 case EXTENSION_SETTINGS: 794 return "google_chrome_extension_settings"; 795 case APP_NOTIFICATIONS: 796 return "google_chrome_app_notifications"; 797 case HISTORY_DELETE_DIRECTIVES: 798 return "google_chrome_history_delete_directives"; 799 case SYNCED_NOTIFICATIONS: 800 return "google_chrome_synced_notifications"; 801 case SYNCED_NOTIFICATION_APP_INFO: 802 return "google_chrome_synced_notification_app_info"; 803 case DEVICE_INFO: 804 return "google_chrome_device_info"; 805 case EXPERIMENTS: 806 return "google_chrome_experiments"; 807 case PRIORITY_PREFERENCES: 808 return "google_chrome_priority_preferences"; 809 case DICTIONARY: 810 return "google_chrome_dictionary"; 811 case FAVICON_IMAGES: 812 return "google_chrome_favicon_images"; 813 case FAVICON_TRACKING: 814 return "google_chrome_favicon_tracking"; 815 case SUPERVISED_USER_SETTINGS: 816 return "google_chrome_managed_user_settings"; 817 case SUPERVISED_USERS: 818 return "google_chrome_managed_users"; 819 case SUPERVISED_USER_SHARED_SETTINGS: 820 return "google_chrome_managed_user_shared_settings"; 821 case ARTICLES: 822 return "google_chrome_articles"; 823 case PROXY_TABS: 824 return std::string(); 825 default: 826 break; 827 } 828 NOTREACHED() << "No known extension for model type."; 829 return "INVALID"; 830 } 831 832 // TODO(akalin): Figure out a better way to do these mappings. 833 // Note: Do not include proxy types in this list. They should never receive 834 // or trigger notifications. 835 namespace { 836 const char kBookmarkNotificationType[] = "BOOKMARK"; 837 const char kPreferenceNotificationType[] = "PREFERENCE"; 838 const char kPasswordNotificationType[] = "PASSWORD"; 839 const char kAutofillNotificationType[] = "AUTOFILL"; 840 const char kThemeNotificationType[] = "THEME"; 841 const char kTypedUrlNotificationType[] = "TYPED_URL"; 842 const char kExtensionNotificationType[] = "EXTENSION"; 843 const char kExtensionSettingNotificationType[] = "EXTENSION_SETTING"; 844 const char kNigoriNotificationType[] = "NIGORI"; 845 const char kAppSettingNotificationType[] = "APP_SETTING"; 846 const char kAppNotificationType[] = "APP"; 847 const char kAppListNotificationType[] = "APP_LIST"; 848 const char kSearchEngineNotificationType[] = "SEARCH_ENGINE"; 849 const char kSessionNotificationType[] = "SESSION"; 850 const char kAutofillProfileNotificationType[] = "AUTOFILL_PROFILE"; 851 const char kAppNotificationNotificationType[] = "APP_NOTIFICATION"; 852 const char kHistoryDeleteDirectiveNotificationType[] = 853 "HISTORY_DELETE_DIRECTIVE"; 854 const char kSyncedNotificationType[] = "SYNCED_NOTIFICATION"; 855 const char kSyncedNotificationAppInfoType[] = "SYNCED_NOTIFICATION_APP_INFO"; 856 const char kDeviceInfoNotificationType[] = "DEVICE_INFO"; 857 const char kExperimentsNotificationType[] = "EXPERIMENTS"; 858 const char kPriorityPreferenceNotificationType[] = "PRIORITY_PREFERENCE"; 859 const char kDictionaryNotificationType[] = "DICTIONARY"; 860 const char kFaviconImageNotificationType[] = "FAVICON_IMAGE"; 861 const char kFaviconTrackingNotificationType[] = "FAVICON_TRACKING"; 862 const char kSupervisedUserSettingNotificationType[] = "MANAGED_USER_SETTING"; 863 const char kSupervisedUserNotificationType[] = "MANAGED_USER"; 864 const char kSupervisedUserSharedSettingNotificationType[] = 865 "MANAGED_USER_SHARED_SETTING"; 866 const char kArticleNotificationType[] = "ARTICLE"; 867 } // namespace 868 869 bool RealModelTypeToNotificationType(ModelType model_type, 870 std::string* notification_type) { 871 switch (model_type) { 872 case BOOKMARKS: 873 *notification_type = kBookmarkNotificationType; 874 return true; 875 case PREFERENCES: 876 *notification_type = kPreferenceNotificationType; 877 return true; 878 case PASSWORDS: 879 *notification_type = kPasswordNotificationType; 880 return true; 881 case AUTOFILL: 882 *notification_type = kAutofillNotificationType; 883 return true; 884 case THEMES: 885 *notification_type = kThemeNotificationType; 886 return true; 887 case TYPED_URLS: 888 *notification_type = kTypedUrlNotificationType; 889 return true; 890 case EXTENSIONS: 891 *notification_type = kExtensionNotificationType; 892 return true; 893 case NIGORI: 894 *notification_type = kNigoriNotificationType; 895 return true; 896 case APP_SETTINGS: 897 *notification_type = kAppSettingNotificationType; 898 return true; 899 case APPS: 900 *notification_type = kAppNotificationType; 901 return true; 902 case APP_LIST: 903 *notification_type = kAppListNotificationType; 904 return true; 905 case SEARCH_ENGINES: 906 *notification_type = kSearchEngineNotificationType; 907 return true; 908 case SESSIONS: 909 *notification_type = kSessionNotificationType; 910 return true; 911 case AUTOFILL_PROFILE: 912 *notification_type = kAutofillProfileNotificationType; 913 return true; 914 case EXTENSION_SETTINGS: 915 *notification_type = kExtensionSettingNotificationType; 916 return true; 917 case APP_NOTIFICATIONS: 918 *notification_type = kAppNotificationNotificationType; 919 return true; 920 case HISTORY_DELETE_DIRECTIVES: 921 *notification_type = kHistoryDeleteDirectiveNotificationType; 922 return true; 923 case SYNCED_NOTIFICATIONS: 924 *notification_type = kSyncedNotificationType; 925 return true; 926 case SYNCED_NOTIFICATION_APP_INFO: 927 *notification_type = kSyncedNotificationAppInfoType; 928 return true; 929 case DEVICE_INFO: 930 *notification_type = kDeviceInfoNotificationType; 931 return true; 932 case EXPERIMENTS: 933 *notification_type = kExperimentsNotificationType; 934 return true; 935 case PRIORITY_PREFERENCES: 936 *notification_type = kPriorityPreferenceNotificationType; 937 return true; 938 case DICTIONARY: 939 *notification_type = kDictionaryNotificationType; 940 return true; 941 case FAVICON_IMAGES: 942 *notification_type = kFaviconImageNotificationType; 943 return true; 944 case FAVICON_TRACKING: 945 *notification_type = kFaviconTrackingNotificationType; 946 return true; 947 case SUPERVISED_USER_SETTINGS: 948 *notification_type = kSupervisedUserSettingNotificationType; 949 return true; 950 case SUPERVISED_USERS: 951 *notification_type = kSupervisedUserNotificationType; 952 return true; 953 case SUPERVISED_USER_SHARED_SETTINGS: 954 *notification_type = kSupervisedUserSharedSettingNotificationType; 955 return true; 956 case ARTICLES: 957 *notification_type = kArticleNotificationType; 958 return true; 959 default: 960 break; 961 } 962 notification_type->clear(); 963 return false; 964 } 965 966 bool NotificationTypeToRealModelType(const std::string& notification_type, 967 ModelType* model_type) { 968 if (notification_type == kBookmarkNotificationType) { 969 *model_type = BOOKMARKS; 970 return true; 971 } else if (notification_type == kPreferenceNotificationType) { 972 *model_type = PREFERENCES; 973 return true; 974 } else if (notification_type == kPasswordNotificationType) { 975 *model_type = PASSWORDS; 976 return true; 977 } else if (notification_type == kAutofillNotificationType) { 978 *model_type = AUTOFILL; 979 return true; 980 } else if (notification_type == kThemeNotificationType) { 981 *model_type = THEMES; 982 return true; 983 } else if (notification_type == kTypedUrlNotificationType) { 984 *model_type = TYPED_URLS; 985 return true; 986 } else if (notification_type == kExtensionNotificationType) { 987 *model_type = EXTENSIONS; 988 return true; 989 } else if (notification_type == kNigoriNotificationType) { 990 *model_type = NIGORI; 991 return true; 992 } else if (notification_type == kAppNotificationType) { 993 *model_type = APPS; 994 return true; 995 } else if (notification_type == kAppListNotificationType) { 996 *model_type = APP_LIST; 997 return true; 998 } else if (notification_type == kSearchEngineNotificationType) { 999 *model_type = SEARCH_ENGINES; 1000 return true; 1001 } else if (notification_type == kSessionNotificationType) { 1002 *model_type = SESSIONS; 1003 return true; 1004 } else if (notification_type == kAutofillProfileNotificationType) { 1005 *model_type = AUTOFILL_PROFILE; 1006 return true; 1007 } else if (notification_type == kAppSettingNotificationType) { 1008 *model_type = APP_SETTINGS; 1009 return true; 1010 } else if (notification_type == kExtensionSettingNotificationType) { 1011 *model_type = EXTENSION_SETTINGS; 1012 return true; 1013 } else if (notification_type == kAppNotificationNotificationType) { 1014 *model_type = APP_NOTIFICATIONS; 1015 return true; 1016 } else if (notification_type == kHistoryDeleteDirectiveNotificationType) { 1017 *model_type = HISTORY_DELETE_DIRECTIVES; 1018 return true; 1019 } else if (notification_type == kSyncedNotificationType) { 1020 *model_type = SYNCED_NOTIFICATIONS; 1021 return true; 1022 } else if (notification_type == kSyncedNotificationAppInfoType) { 1023 *model_type = SYNCED_NOTIFICATION_APP_INFO; 1024 return true; 1025 } else if (notification_type == kDeviceInfoNotificationType) { 1026 *model_type = DEVICE_INFO; 1027 return true; 1028 } else if (notification_type == kExperimentsNotificationType) { 1029 *model_type = EXPERIMENTS; 1030 return true; 1031 } else if (notification_type == kPriorityPreferenceNotificationType) { 1032 *model_type = PRIORITY_PREFERENCES; 1033 return true; 1034 } else if (notification_type == kDictionaryNotificationType) { 1035 *model_type = DICTIONARY; 1036 return true; 1037 } else if (notification_type == kFaviconImageNotificationType) { 1038 *model_type = FAVICON_IMAGES; 1039 return true; 1040 } else if (notification_type == kFaviconTrackingNotificationType) { 1041 *model_type = FAVICON_TRACKING; 1042 return true; 1043 } else if (notification_type == kSupervisedUserSettingNotificationType) { 1044 *model_type = SUPERVISED_USER_SETTINGS; 1045 return true; 1046 } else if (notification_type == kSupervisedUserNotificationType) { 1047 *model_type = SUPERVISED_USERS; 1048 return true; 1049 } else if (notification_type == 1050 kSupervisedUserSharedSettingNotificationType) { 1051 *model_type = SUPERVISED_USER_SHARED_SETTINGS; 1052 return true; 1053 } else if (notification_type == kArticleNotificationType) { 1054 *model_type = ARTICLES; 1055 return true; 1056 } 1057 *model_type = UNSPECIFIED; 1058 return false; 1059 } 1060 1061 bool IsRealDataType(ModelType model_type) { 1062 return model_type >= FIRST_REAL_MODEL_TYPE && model_type < MODEL_TYPE_COUNT; 1063 } 1064 1065 bool IsProxyType(ModelType model_type) { 1066 return model_type >= FIRST_PROXY_TYPE && model_type <= LAST_PROXY_TYPE; 1067 } 1068 1069 bool IsActOnceDataType(ModelType model_type) { 1070 return model_type == HISTORY_DELETE_DIRECTIVES; 1071 } 1072 1073 } // namespace syncer 1074