| OLD | NEW |
| (Empty) |
| 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 <stddef.h> | |
| 8 | |
| 9 #include "base/macros.h" | |
| 10 #include "base/strings/string_split.h" | |
| 11 #include "base/values.h" | |
| 12 #include "sync/protocol/app_notification_specifics.pb.h" | |
| 13 #include "sync/protocol/app_setting_specifics.pb.h" | |
| 14 #include "sync/protocol/app_specifics.pb.h" | |
| 15 #include "sync/protocol/autofill_specifics.pb.h" | |
| 16 #include "sync/protocol/bookmark_specifics.pb.h" | |
| 17 #include "sync/protocol/extension_setting_specifics.pb.h" | |
| 18 #include "sync/protocol/extension_specifics.pb.h" | |
| 19 #include "sync/protocol/nigori_specifics.pb.h" | |
| 20 #include "sync/protocol/password_specifics.pb.h" | |
| 21 #include "sync/protocol/preference_specifics.pb.h" | |
| 22 #include "sync/protocol/search_engine_specifics.pb.h" | |
| 23 #include "sync/protocol/session_specifics.pb.h" | |
| 24 #include "sync/protocol/sync.pb.h" | |
| 25 #include "sync/protocol/theme_specifics.pb.h" | |
| 26 #include "sync/protocol/typed_url_specifics.pb.h" | |
| 27 #include "sync/syncable/syncable_proto_util.h" | |
| 28 | |
| 29 namespace syncer { | |
| 30 | |
| 31 struct ModelTypeInfo { | |
| 32 const ModelType model_type; | |
| 33 // Model Type notification string. | |
| 34 // This needs to match the corresponding proto message name in sync.proto | |
| 35 const char* const notification_type; | |
| 36 // Root tag for Model Type | |
| 37 // This should be the same as the model type but all lowercase. | |
| 38 const char* const root_tag; | |
| 39 // String value for Model Type | |
| 40 // This should be the same as the model type but space separated and the | |
| 41 // first letter of every word capitalized. | |
| 42 const char* const model_type_string; | |
| 43 // SpecificsFieldNumber for Model Type | |
| 44 const int specifics_field_number; | |
| 45 // Histogram value should be unique for the Model Type, Existing histogram | |
| 46 // values should never be modified without updating "SyncModelTypes" enum in | |
| 47 // histograms.xml to maintain backward compatibility. | |
| 48 const int model_type_histogram_val; | |
| 49 }; | |
| 50 | |
| 51 // Below struct entries are in the same order as their definition in the | |
| 52 // ModelType enum. Don't forget to update the ModelType enum when you make | |
| 53 // changes to this list. | |
| 54 // Struct field values should be unique across the entire map. | |
| 55 const ModelTypeInfo kModelTypeInfoMap[] = { | |
| 56 {UNSPECIFIED, "", "", "Unspecified", -1, 0}, | |
| 57 {TOP_LEVEL_FOLDER, "", "", "Top Level Folder", -1, 1}, | |
| 58 {BOOKMARKS, "BOOKMARK", "bookmarks", "Bookmarks", | |
| 59 sync_pb::EntitySpecifics::kBookmarkFieldNumber, 2}, | |
| 60 {PREFERENCES, "PREFERENCE", "preferences", "Preferences", | |
| 61 sync_pb::EntitySpecifics::kPreferenceFieldNumber, 3}, | |
| 62 {PASSWORDS, "PASSWORD", "passwords", "Passwords", | |
| 63 sync_pb::EntitySpecifics::kPasswordFieldNumber, 4}, | |
| 64 {AUTOFILL_PROFILE, "AUTOFILL_PROFILE", "autofill_profiles", | |
| 65 "Autofill Profiles", sync_pb::EntitySpecifics::kAutofillProfileFieldNumber, | |
| 66 5}, | |
| 67 {AUTOFILL, "AUTOFILL", "autofill", "Autofill", | |
| 68 sync_pb::EntitySpecifics::kAutofillFieldNumber, 6}, | |
| 69 {AUTOFILL_WALLET_DATA, "AUTOFILL_WALLET", "autofill_wallet", | |
| 70 "Autofill Wallet", sync_pb::EntitySpecifics::kAutofillWalletFieldNumber, | |
| 71 34}, | |
| 72 {AUTOFILL_WALLET_METADATA, "WALLET_METADATA", | |
| 73 "autofill_wallet_metadata", "Autofill Wallet Metadata", | |
| 74 sync_pb::EntitySpecifics::kWalletMetadataFieldNumber, 35}, | |
| 75 {THEMES, "THEME", "themes", "Themes", | |
| 76 sync_pb::EntitySpecifics::kThemeFieldNumber, 7}, | |
| 77 {TYPED_URLS, "TYPED_URL", "typed_urls", "Typed URLs", | |
| 78 sync_pb::EntitySpecifics::kTypedUrlFieldNumber, 8}, | |
| 79 {EXTENSIONS, "EXTENSION", "extensions", "Extensions", | |
| 80 sync_pb::EntitySpecifics::kExtensionFieldNumber, 9}, | |
| 81 {SEARCH_ENGINES, "SEARCH_ENGINE", "search_engines", "Search Engines", | |
| 82 sync_pb::EntitySpecifics::kSearchEngineFieldNumber, 10}, | |
| 83 {SESSIONS, "SESSION", "sessions", "Sessions", | |
| 84 sync_pb::EntitySpecifics::kSessionFieldNumber, 11}, | |
| 85 {APPS, "APP", "apps", "Apps", sync_pb::EntitySpecifics::kAppFieldNumber, | |
| 86 12}, | |
| 87 {APP_SETTINGS, "APP_SETTING", "app_settings", "App settings", | |
| 88 sync_pb::EntitySpecifics::kAppSettingFieldNumber, 13}, | |
| 89 {EXTENSION_SETTINGS, "EXTENSION_SETTING", "extension_settings", | |
| 90 "Extension settings", | |
| 91 sync_pb::EntitySpecifics::kExtensionSettingFieldNumber, 14}, | |
| 92 {APP_NOTIFICATIONS, "APP_NOTIFICATION", "app_notifications", | |
| 93 "App Notifications", sync_pb::EntitySpecifics::kAppNotificationFieldNumber, | |
| 94 15}, | |
| 95 {HISTORY_DELETE_DIRECTIVES, "HISTORY_DELETE_DIRECTIVE", | |
| 96 "history_delete_directives", "History Delete Directives", | |
| 97 sync_pb::EntitySpecifics::kHistoryDeleteDirectiveFieldNumber, 16}, | |
| 98 {SYNCED_NOTIFICATIONS, "SYNCED_NOTIFICATION", "synced_notifications", | |
| 99 "Synced Notifications", | |
| 100 sync_pb::EntitySpecifics::kSyncedNotificationFieldNumber, 20}, | |
| 101 {SYNCED_NOTIFICATION_APP_INFO, "SYNCED_NOTIFICATION_APP_INFO", | |
| 102 "synced_notification_app_info", "Synced Notification App Info", | |
| 103 sync_pb::EntitySpecifics::kSyncedNotificationAppInfoFieldNumber, 31}, | |
| 104 {DICTIONARY, "DICTIONARY", "dictionary", "Dictionary", | |
| 105 sync_pb::EntitySpecifics::kDictionaryFieldNumber, 22}, | |
| 106 {FAVICON_IMAGES, "FAVICON_IMAGE", "favicon_images", "Favicon Images", | |
| 107 sync_pb::EntitySpecifics::kFaviconImageFieldNumber, 23}, | |
| 108 {FAVICON_TRACKING, "FAVICON_TRACKING", "favicon_tracking", | |
| 109 "Favicon Tracking", sync_pb::EntitySpecifics::kFaviconTrackingFieldNumber, | |
| 110 24}, | |
| 111 {DEVICE_INFO, "DEVICE_INFO", "device_info", "Device Info", | |
| 112 sync_pb::EntitySpecifics::kDeviceInfoFieldNumber, 18}, | |
| 113 {PRIORITY_PREFERENCES, "PRIORITY_PREFERENCE", "priority_preferences", | |
| 114 "Priority Preferences", | |
| 115 sync_pb::EntitySpecifics::kPriorityPreferenceFieldNumber, 21}, | |
| 116 {SUPERVISED_USER_SETTINGS, "MANAGED_USER_SETTING", "managed_user_settings", | |
| 117 "Managed User Settings", | |
| 118 sync_pb::EntitySpecifics::kManagedUserSettingFieldNumber, 26}, | |
| 119 {SUPERVISED_USERS, "MANAGED_USER", "managed_users", "Managed Users", | |
| 120 sync_pb::EntitySpecifics::kManagedUserFieldNumber, 27}, | |
| 121 {SUPERVISED_USER_SHARED_SETTINGS, "MANAGED_USER_SHARED_SETTING", | |
| 122 "managed_user_shared_settings", "Managed User Shared Settings", | |
| 123 sync_pb::EntitySpecifics::kManagedUserSharedSettingFieldNumber, 30}, | |
| 124 {ARTICLES, "ARTICLE", "articles", "Articles", | |
| 125 sync_pb::EntitySpecifics::kArticleFieldNumber, 28}, | |
| 126 {APP_LIST, "APP_LIST", "app_list", "App List", | |
| 127 sync_pb::EntitySpecifics::kAppListFieldNumber, 29}, | |
| 128 {WIFI_CREDENTIALS, "WIFI_CREDENTIAL", "wifi_credentials", | |
| 129 "WiFi Credentials", sync_pb::EntitySpecifics::kWifiCredentialFieldNumber, | |
| 130 32}, | |
| 131 {SUPERVISED_USER_WHITELISTS, "MANAGED_USER_WHITELIST", | |
| 132 "managed_user_whitelists", "Managed User Whitelists", | |
| 133 sync_pb::EntitySpecifics::kManagedUserWhitelistFieldNumber, 33}, | |
| 134 {ARC_PACKAGE, "ARC_PACKAGE", "arc_package", "Arc Package", | |
| 135 sync_pb::EntitySpecifics::kArcPackageFieldNumber, 36}, | |
| 136 {PROXY_TABS, "", "", "Tabs", -1, 25}, | |
| 137 {NIGORI, "NIGORI", "nigori", "Encryption keys", | |
| 138 sync_pb::EntitySpecifics::kNigoriFieldNumber, 17}, | |
| 139 {EXPERIMENTS, "EXPERIMENTS", "experiments", "Experiments", | |
| 140 sync_pb::EntitySpecifics::kExperimentsFieldNumber, 19}, | |
| 141 }; | |
| 142 | |
| 143 static_assert(arraysize(kModelTypeInfoMap) == MODEL_TYPE_COUNT, | |
| 144 "kModelTypeInfoMap should have MODEL_TYPE_COUNT elements"); | |
| 145 | |
| 146 // Notes: | |
| 147 // 1) This list must contain exactly the same elements as the set returned by | |
| 148 // UserSelectableTypes(). | |
| 149 // 2) This list must be in the same order as the respective values in the | |
| 150 // ModelType enum. | |
| 151 const char* kUserSelectableDataTypeNames[] = { | |
| 152 "bookmarks", | |
| 153 "preferences", | |
| 154 "passwords", | |
| 155 "autofill", | |
| 156 "themes", | |
| 157 "typedUrls", | |
| 158 "extensions", | |
| 159 "apps", | |
| 160 "tabs", | |
| 161 }; | |
| 162 | |
| 163 static_assert( | |
| 164 37 == MODEL_TYPE_COUNT, | |
| 165 "update kUserSelectableDataTypeName to match UserSelectableTypes"); | |
| 166 | |
| 167 void AddDefaultFieldValue(ModelType datatype, | |
| 168 sync_pb::EntitySpecifics* specifics) { | |
| 169 if (!ProtocolTypes().Has(datatype)) { | |
| 170 NOTREACHED() << "Only protocol types have field values."; | |
| 171 return; | |
| 172 } | |
| 173 switch (datatype) { | |
| 174 case BOOKMARKS: | |
| 175 specifics->mutable_bookmark(); | |
| 176 break; | |
| 177 case PASSWORDS: | |
| 178 specifics->mutable_password(); | |
| 179 break; | |
| 180 case PREFERENCES: | |
| 181 specifics->mutable_preference(); | |
| 182 break; | |
| 183 case AUTOFILL: | |
| 184 specifics->mutable_autofill(); | |
| 185 break; | |
| 186 case AUTOFILL_PROFILE: | |
| 187 specifics->mutable_autofill_profile(); | |
| 188 break; | |
| 189 case AUTOFILL_WALLET_DATA: | |
| 190 specifics->mutable_autofill_wallet(); | |
| 191 break; | |
| 192 case AUTOFILL_WALLET_METADATA: | |
| 193 specifics->mutable_wallet_metadata(); | |
| 194 break; | |
| 195 case THEMES: | |
| 196 specifics->mutable_theme(); | |
| 197 break; | |
| 198 case TYPED_URLS: | |
| 199 specifics->mutable_typed_url(); | |
| 200 break; | |
| 201 case EXTENSIONS: | |
| 202 specifics->mutable_extension(); | |
| 203 break; | |
| 204 case NIGORI: | |
| 205 specifics->mutable_nigori(); | |
| 206 break; | |
| 207 case SEARCH_ENGINES: | |
| 208 specifics->mutable_search_engine(); | |
| 209 break; | |
| 210 case SESSIONS: | |
| 211 specifics->mutable_session(); | |
| 212 break; | |
| 213 case APPS: | |
| 214 specifics->mutable_app(); | |
| 215 break; | |
| 216 case APP_LIST: | |
| 217 specifics->mutable_app_list(); | |
| 218 break; | |
| 219 case APP_SETTINGS: | |
| 220 specifics->mutable_app_setting(); | |
| 221 break; | |
| 222 case ARC_PACKAGE: | |
| 223 specifics->mutable_arc_package(); | |
| 224 break; | |
| 225 case EXTENSION_SETTINGS: | |
| 226 specifics->mutable_extension_setting(); | |
| 227 break; | |
| 228 case APP_NOTIFICATIONS: | |
| 229 specifics->mutable_app_notification(); | |
| 230 break; | |
| 231 case HISTORY_DELETE_DIRECTIVES: | |
| 232 specifics->mutable_history_delete_directive(); | |
| 233 break; | |
| 234 case SYNCED_NOTIFICATIONS: | |
| 235 specifics->mutable_synced_notification(); | |
| 236 break; | |
| 237 case SYNCED_NOTIFICATION_APP_INFO: | |
| 238 specifics->mutable_synced_notification_app_info(); | |
| 239 break; | |
| 240 case DEVICE_INFO: | |
| 241 specifics->mutable_device_info(); | |
| 242 break; | |
| 243 case EXPERIMENTS: | |
| 244 specifics->mutable_experiments(); | |
| 245 break; | |
| 246 case PRIORITY_PREFERENCES: | |
| 247 specifics->mutable_priority_preference(); | |
| 248 break; | |
| 249 case DICTIONARY: | |
| 250 specifics->mutable_dictionary(); | |
| 251 break; | |
| 252 case FAVICON_IMAGES: | |
| 253 specifics->mutable_favicon_image(); | |
| 254 break; | |
| 255 case FAVICON_TRACKING: | |
| 256 specifics->mutable_favicon_tracking(); | |
| 257 break; | |
| 258 case SUPERVISED_USER_SETTINGS: | |
| 259 specifics->mutable_managed_user_setting(); | |
| 260 break; | |
| 261 case SUPERVISED_USERS: | |
| 262 specifics->mutable_managed_user(); | |
| 263 break; | |
| 264 case SUPERVISED_USER_SHARED_SETTINGS: | |
| 265 specifics->mutable_managed_user_shared_setting(); | |
| 266 break; | |
| 267 case SUPERVISED_USER_WHITELISTS: | |
| 268 specifics->mutable_managed_user_whitelist(); | |
| 269 break; | |
| 270 case ARTICLES: | |
| 271 specifics->mutable_article(); | |
| 272 break; | |
| 273 case WIFI_CREDENTIALS: | |
| 274 specifics->mutable_wifi_credential(); | |
| 275 break; | |
| 276 default: | |
| 277 NOTREACHED() << "No known extension for model type."; | |
| 278 } | |
| 279 } | |
| 280 | |
| 281 ModelType GetModelTypeFromSpecificsFieldNumber(int field_number) { | |
| 282 ModelTypeSet protocol_types = ProtocolTypes(); | |
| 283 for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); | |
| 284 iter.Inc()) { | |
| 285 if (GetSpecificsFieldNumberFromModelType(iter.Get()) == field_number) | |
| 286 return iter.Get(); | |
| 287 } | |
| 288 return UNSPECIFIED; | |
| 289 } | |
| 290 | |
| 291 int GetSpecificsFieldNumberFromModelType(ModelType model_type) { | |
| 292 DCHECK(ProtocolTypes().Has(model_type)) | |
| 293 << "Only protocol types have field values."; | |
| 294 if (ProtocolTypes().Has(model_type)) | |
| 295 return kModelTypeInfoMap[model_type].specifics_field_number; | |
| 296 NOTREACHED() << "No known extension for model type."; | |
| 297 return 0; | |
| 298 } | |
| 299 | |
| 300 FullModelTypeSet ToFullModelTypeSet(ModelTypeSet in) { | |
| 301 FullModelTypeSet out; | |
| 302 for (ModelTypeSet::Iterator i = in.First(); i.Good(); i.Inc()) { | |
| 303 out.Put(i.Get()); | |
| 304 } | |
| 305 return out; | |
| 306 } | |
| 307 | |
| 308 // Note: keep this consistent with GetModelType in entry.cc! | |
| 309 ModelType GetModelType(const sync_pb::SyncEntity& sync_entity) { | |
| 310 DCHECK(!IsRoot(sync_entity)); // Root shouldn't ever go over the wire. | |
| 311 | |
| 312 // Backwards compatibility with old (pre-specifics) protocol. | |
| 313 if (sync_entity.has_bookmarkdata()) | |
| 314 return BOOKMARKS; | |
| 315 | |
| 316 ModelType specifics_type = GetModelTypeFromSpecifics(sync_entity.specifics()); | |
| 317 if (specifics_type != UNSPECIFIED) | |
| 318 return specifics_type; | |
| 319 | |
| 320 // Loose check for server-created top-level folders that aren't | |
| 321 // bound to a particular model type. | |
| 322 if (!sync_entity.server_defined_unique_tag().empty() && | |
| 323 IsFolder(sync_entity)) { | |
| 324 return TOP_LEVEL_FOLDER; | |
| 325 } | |
| 326 | |
| 327 // This is an item of a datatype we can't understand. Maybe it's | |
| 328 // from the future? Either we mis-encoded the object, or the | |
| 329 // server sent us entries it shouldn't have. | |
| 330 NOTREACHED() << "Unknown datatype in sync proto."; | |
| 331 return UNSPECIFIED; | |
| 332 } | |
| 333 | |
| 334 ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics) { | |
| 335 if (specifics.has_bookmark()) | |
| 336 return BOOKMARKS; | |
| 337 | |
| 338 if (specifics.has_password()) | |
| 339 return PASSWORDS; | |
| 340 | |
| 341 if (specifics.has_preference()) | |
| 342 return PREFERENCES; | |
| 343 | |
| 344 if (specifics.has_autofill()) | |
| 345 return AUTOFILL; | |
| 346 | |
| 347 if (specifics.has_autofill_profile()) | |
| 348 return AUTOFILL_PROFILE; | |
| 349 | |
| 350 if (specifics.has_autofill_wallet()) | |
| 351 return AUTOFILL_WALLET_DATA; | |
| 352 | |
| 353 if (specifics.has_wallet_metadata()) | |
| 354 return AUTOFILL_WALLET_METADATA; | |
| 355 | |
| 356 if (specifics.has_theme()) | |
| 357 return THEMES; | |
| 358 | |
| 359 if (specifics.has_typed_url()) | |
| 360 return TYPED_URLS; | |
| 361 | |
| 362 if (specifics.has_extension()) | |
| 363 return EXTENSIONS; | |
| 364 | |
| 365 if (specifics.has_nigori()) | |
| 366 return NIGORI; | |
| 367 | |
| 368 if (specifics.has_app()) | |
| 369 return APPS; | |
| 370 | |
| 371 if (specifics.has_app_list()) | |
| 372 return APP_LIST; | |
| 373 | |
| 374 if (specifics.has_arc_package()) | |
| 375 return ARC_PACKAGE; | |
| 376 | |
| 377 if (specifics.has_search_engine()) | |
| 378 return SEARCH_ENGINES; | |
| 379 | |
| 380 if (specifics.has_session()) | |
| 381 return SESSIONS; | |
| 382 | |
| 383 if (specifics.has_app_setting()) | |
| 384 return APP_SETTINGS; | |
| 385 | |
| 386 if (specifics.has_extension_setting()) | |
| 387 return EXTENSION_SETTINGS; | |
| 388 | |
| 389 if (specifics.has_app_notification()) | |
| 390 return APP_NOTIFICATIONS; | |
| 391 | |
| 392 if (specifics.has_history_delete_directive()) | |
| 393 return HISTORY_DELETE_DIRECTIVES; | |
| 394 | |
| 395 if (specifics.has_synced_notification()) | |
| 396 return SYNCED_NOTIFICATIONS; | |
| 397 | |
| 398 if (specifics.has_synced_notification_app_info()) | |
| 399 return SYNCED_NOTIFICATION_APP_INFO; | |
| 400 | |
| 401 if (specifics.has_device_info()) | |
| 402 return DEVICE_INFO; | |
| 403 | |
| 404 if (specifics.has_experiments()) | |
| 405 return EXPERIMENTS; | |
| 406 | |
| 407 if (specifics.has_priority_preference()) | |
| 408 return PRIORITY_PREFERENCES; | |
| 409 | |
| 410 if (specifics.has_dictionary()) | |
| 411 return DICTIONARY; | |
| 412 | |
| 413 if (specifics.has_favicon_image()) | |
| 414 return FAVICON_IMAGES; | |
| 415 | |
| 416 if (specifics.has_favicon_tracking()) | |
| 417 return FAVICON_TRACKING; | |
| 418 | |
| 419 if (specifics.has_managed_user_setting()) | |
| 420 return SUPERVISED_USER_SETTINGS; | |
| 421 | |
| 422 if (specifics.has_managed_user()) | |
| 423 return SUPERVISED_USERS; | |
| 424 | |
| 425 if (specifics.has_managed_user_shared_setting()) | |
| 426 return SUPERVISED_USER_SHARED_SETTINGS; | |
| 427 | |
| 428 if (specifics.has_managed_user_whitelist()) | |
| 429 return SUPERVISED_USER_WHITELISTS; | |
| 430 | |
| 431 if (specifics.has_article()) | |
| 432 return ARTICLES; | |
| 433 | |
| 434 if (specifics.has_wifi_credential()) | |
| 435 return WIFI_CREDENTIALS; | |
| 436 | |
| 437 return UNSPECIFIED; | |
| 438 } | |
| 439 | |
| 440 ModelTypeSet ProtocolTypes() { | |
| 441 ModelTypeSet set = ModelTypeSet::All(); | |
| 442 set.RemoveAll(ProxyTypes()); | |
| 443 return set; | |
| 444 } | |
| 445 | |
| 446 ModelTypeSet UserTypes() { | |
| 447 ModelTypeSet set; | |
| 448 // TODO(sync): We should be able to build the actual enumset's internal | |
| 449 // bitset value here at compile time, rather than performing an iteration | |
| 450 // every time. | |
| 451 for (int i = FIRST_USER_MODEL_TYPE; i <= LAST_USER_MODEL_TYPE; ++i) { | |
| 452 set.Put(ModelTypeFromInt(i)); | |
| 453 } | |
| 454 return set; | |
| 455 } | |
| 456 | |
| 457 ModelTypeSet UserSelectableTypes() { | |
| 458 ModelTypeSet set; | |
| 459 // Although the order doesn't technically matter here, it's clearer to keep | |
| 460 // these in the same order as their definition in the ModelType enum. | |
| 461 set.Put(BOOKMARKS); | |
| 462 set.Put(PREFERENCES); | |
| 463 set.Put(PASSWORDS); | |
| 464 set.Put(AUTOFILL); | |
| 465 set.Put(THEMES); | |
| 466 set.Put(TYPED_URLS); | |
| 467 set.Put(EXTENSIONS); | |
| 468 set.Put(APPS); | |
| 469 set.Put(PROXY_TABS); | |
| 470 return set; | |
| 471 } | |
| 472 | |
| 473 bool IsUserSelectableType(ModelType model_type) { | |
| 474 return UserSelectableTypes().Has(model_type); | |
| 475 } | |
| 476 | |
| 477 ModelTypeNameMap GetUserSelectableTypeNameMap() { | |
| 478 ModelTypeNameMap type_names; | |
| 479 ModelTypeSet type_set = UserSelectableTypes(); | |
| 480 ModelTypeSet::Iterator it = type_set.First(); | |
| 481 DCHECK_EQ(arraysize(kUserSelectableDataTypeNames), type_set.Size()); | |
| 482 for (size_t i = 0; i < arraysize(kUserSelectableDataTypeNames) && it.Good(); | |
| 483 ++i, it.Inc()) { | |
| 484 type_names[it.Get()] = kUserSelectableDataTypeNames[i]; | |
| 485 } | |
| 486 return type_names; | |
| 487 } | |
| 488 | |
| 489 ModelTypeSet EncryptableUserTypes() { | |
| 490 ModelTypeSet encryptable_user_types = UserTypes(); | |
| 491 // We never encrypt history delete directives. | |
| 492 encryptable_user_types.Remove(HISTORY_DELETE_DIRECTIVES); | |
| 493 // Synced notifications are not encrypted since the server must see changes. | |
| 494 encryptable_user_types.Remove(SYNCED_NOTIFICATIONS); | |
| 495 // Synced Notification App Info does not have private data, so it is not | |
| 496 // encrypted. | |
| 497 encryptable_user_types.Remove(SYNCED_NOTIFICATION_APP_INFO); | |
| 498 // Device info data is not encrypted because it might be synced before | |
| 499 // encryption is ready. | |
| 500 encryptable_user_types.Remove(DEVICE_INFO); | |
| 501 // Priority preferences are not encrypted because they might be synced before | |
| 502 // encryption is ready. | |
| 503 encryptable_user_types.Remove(PRIORITY_PREFERENCES); | |
| 504 // Supervised user settings are not encrypted since they are set server-side. | |
| 505 encryptable_user_types.Remove(SUPERVISED_USER_SETTINGS); | |
| 506 // Supervised users are not encrypted since they are managed server-side. | |
| 507 encryptable_user_types.Remove(SUPERVISED_USERS); | |
| 508 // Supervised user shared settings are not encrypted since they are managed | |
| 509 // server-side and shared between manager and supervised user. | |
| 510 encryptable_user_types.Remove(SUPERVISED_USER_SHARED_SETTINGS); | |
| 511 // Supervised user whitelists are not encrypted since they are managed | |
| 512 // server-side. | |
| 513 encryptable_user_types.Remove(SUPERVISED_USER_WHITELISTS); | |
| 514 // Proxy types have no sync representation and are therefore not encrypted. | |
| 515 // Note however that proxy types map to one or more protocol types, which | |
| 516 // may or may not be encrypted themselves. | |
| 517 encryptable_user_types.RemoveAll(ProxyTypes()); | |
| 518 // Wallet data is not encrypted since it actually originates on the server. | |
| 519 encryptable_user_types.Remove(AUTOFILL_WALLET_DATA); | |
| 520 return encryptable_user_types; | |
| 521 } | |
| 522 | |
| 523 ModelTypeSet PriorityUserTypes() { | |
| 524 return ModelTypeSet(DEVICE_INFO, PRIORITY_PREFERENCES); | |
| 525 } | |
| 526 | |
| 527 ModelTypeSet ControlTypes() { | |
| 528 ModelTypeSet set; | |
| 529 // TODO(sync): We should be able to build the actual enumset's internal | |
| 530 // bitset value here at compile time, rather than performing an iteration | |
| 531 // every time. | |
| 532 for (int i = FIRST_CONTROL_MODEL_TYPE; i <= LAST_CONTROL_MODEL_TYPE; ++i) { | |
| 533 set.Put(ModelTypeFromInt(i)); | |
| 534 } | |
| 535 | |
| 536 return set; | |
| 537 } | |
| 538 | |
| 539 ModelTypeSet ProxyTypes() { | |
| 540 ModelTypeSet set; | |
| 541 set.Put(PROXY_TABS); | |
| 542 return set; | |
| 543 } | |
| 544 | |
| 545 bool IsControlType(ModelType model_type) { | |
| 546 return ControlTypes().Has(model_type); | |
| 547 } | |
| 548 | |
| 549 ModelTypeSet CoreTypes() { | |
| 550 syncer::ModelTypeSet result; | |
| 551 result.PutAll(PriorityCoreTypes()); | |
| 552 | |
| 553 // The following are low priority core types. | |
| 554 result.Put(SYNCED_NOTIFICATIONS); | |
| 555 result.Put(SYNCED_NOTIFICATION_APP_INFO); | |
| 556 result.Put(SUPERVISED_USER_SHARED_SETTINGS); | |
| 557 result.Put(SUPERVISED_USER_WHITELISTS); | |
| 558 | |
| 559 return result; | |
| 560 } | |
| 561 | |
| 562 ModelTypeSet PriorityCoreTypes() { | |
| 563 syncer::ModelTypeSet result; | |
| 564 result.PutAll(ControlTypes()); | |
| 565 | |
| 566 // The following are non-control core types. | |
| 567 result.Put(SUPERVISED_USERS); | |
| 568 result.Put(SUPERVISED_USER_SETTINGS); | |
| 569 | |
| 570 return result; | |
| 571 } | |
| 572 | |
| 573 const char* ModelTypeToString(ModelType model_type) { | |
| 574 // This is used in serialization routines as well as for displaying debug | |
| 575 // information. Do not attempt to change these string values unless you know | |
| 576 // what you're doing. | |
| 577 if (model_type >= UNSPECIFIED && model_type < MODEL_TYPE_COUNT) | |
| 578 return kModelTypeInfoMap[model_type].model_type_string; | |
| 579 NOTREACHED() << "No known extension for model type."; | |
| 580 return "INVALID"; | |
| 581 } | |
| 582 | |
| 583 // The normal rules about histograms apply here. Always append to the bottom of | |
| 584 // the list, and be careful to not reuse integer values that have already been | |
| 585 // assigned. | |
| 586 // | |
| 587 // Don't forget to update the "SyncModelTypes" enum in histograms.xml when you | |
| 588 // make changes to this list. | |
| 589 int ModelTypeToHistogramInt(ModelType model_type) { | |
| 590 if (model_type >= UNSPECIFIED && model_type < MODEL_TYPE_COUNT) | |
| 591 return kModelTypeInfoMap[model_type].model_type_histogram_val; | |
| 592 return 0; | |
| 593 } | |
| 594 | |
| 595 base::StringValue* ModelTypeToValue(ModelType model_type) { | |
| 596 if (model_type >= FIRST_REAL_MODEL_TYPE) { | |
| 597 return new base::StringValue(ModelTypeToString(model_type)); | |
| 598 } else if (model_type == TOP_LEVEL_FOLDER) { | |
| 599 return new base::StringValue("Top-level folder"); | |
| 600 } else if (model_type == UNSPECIFIED) { | |
| 601 return new base::StringValue("Unspecified"); | |
| 602 } | |
| 603 NOTREACHED(); | |
| 604 return new base::StringValue(std::string()); | |
| 605 } | |
| 606 | |
| 607 ModelType ModelTypeFromValue(const base::Value& value) { | |
| 608 if (value.IsType(base::Value::TYPE_STRING)) { | |
| 609 std::string result; | |
| 610 CHECK(value.GetAsString(&result)); | |
| 611 return ModelTypeFromString(result); | |
| 612 } else if (value.IsType(base::Value::TYPE_INTEGER)) { | |
| 613 int result; | |
| 614 CHECK(value.GetAsInteger(&result)); | |
| 615 return ModelTypeFromInt(result); | |
| 616 } else { | |
| 617 NOTREACHED() << "Unsupported value type: " << value.GetType(); | |
| 618 return UNSPECIFIED; | |
| 619 } | |
| 620 } | |
| 621 | |
| 622 ModelType ModelTypeFromString(const std::string& model_type_string) { | |
| 623 if (model_type_string != "Unspecified" && | |
| 624 model_type_string != "Top Level Folder") { | |
| 625 for (size_t i = 0; i < arraysize(kModelTypeInfoMap); ++i) { | |
| 626 if (kModelTypeInfoMap[i].model_type_string == model_type_string) | |
| 627 return kModelTypeInfoMap[i].model_type; | |
| 628 } | |
| 629 } | |
| 630 NOTREACHED() << "No known model type corresponding to " << model_type_string | |
| 631 << "."; | |
| 632 return UNSPECIFIED; | |
| 633 } | |
| 634 | |
| 635 std::string ModelTypeSetToString(ModelTypeSet model_types) { | |
| 636 std::string result; | |
| 637 for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) { | |
| 638 if (!result.empty()) { | |
| 639 result += ", "; | |
| 640 } | |
| 641 result += ModelTypeToString(it.Get()); | |
| 642 } | |
| 643 return result; | |
| 644 } | |
| 645 | |
| 646 std::ostream& operator<<(std::ostream& out, ModelTypeSet model_type_set) { | |
| 647 return out << ModelTypeSetToString(model_type_set); | |
| 648 } | |
| 649 | |
| 650 ModelTypeSet ModelTypeSetFromString(const std::string& model_types_string) { | |
| 651 std::string working_copy = model_types_string; | |
| 652 ModelTypeSet model_types; | |
| 653 while (!working_copy.empty()) { | |
| 654 // Remove any leading spaces. | |
| 655 working_copy = working_copy.substr(working_copy.find_first_not_of(' ')); | |
| 656 if (working_copy.empty()) | |
| 657 break; | |
| 658 std::string type_str; | |
| 659 size_t end = working_copy.find(','); | |
| 660 if (end == std::string::npos) { | |
| 661 end = working_copy.length() - 1; | |
| 662 type_str = working_copy; | |
| 663 } else { | |
| 664 type_str = working_copy.substr(0, end); | |
| 665 } | |
| 666 syncer::ModelType type = ModelTypeFromString(type_str); | |
| 667 if (IsRealDataType(type)) | |
| 668 model_types.Put(type); | |
| 669 working_copy = working_copy.substr(end + 1); | |
| 670 } | |
| 671 return model_types; | |
| 672 } | |
| 673 | |
| 674 std::unique_ptr<base::ListValue> ModelTypeSetToValue(ModelTypeSet model_types) { | |
| 675 std::unique_ptr<base::ListValue> value(new base::ListValue()); | |
| 676 for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) { | |
| 677 value->AppendString(ModelTypeToString(it.Get())); | |
| 678 } | |
| 679 return value; | |
| 680 } | |
| 681 | |
| 682 ModelTypeSet ModelTypeSetFromValue(const base::ListValue& value) { | |
| 683 ModelTypeSet result; | |
| 684 for (base::ListValue::const_iterator i = value.begin(); | |
| 685 i != value.end(); ++i) { | |
| 686 result.Put(ModelTypeFromValue(**i)); | |
| 687 } | |
| 688 return result; | |
| 689 } | |
| 690 | |
| 691 // TODO(zea): remove all hardcoded tags in model associators and have them use | |
| 692 // this instead. | |
| 693 // NOTE: Proxy types should return empty strings (so that we don't NOTREACHED | |
| 694 // in tests when we verify they have no root node). | |
| 695 std::string ModelTypeToRootTag(ModelType type) { | |
| 696 if (IsProxyType(type)) | |
| 697 return std::string(); | |
| 698 if (IsRealDataType(type)) | |
| 699 return "google_chrome_" + std::string(kModelTypeInfoMap[type].root_tag); | |
| 700 NOTREACHED() << "No known extension for model type."; | |
| 701 return "INVALID"; | |
| 702 } | |
| 703 | |
| 704 const char* GetModelTypeRootTag(ModelType model_type) { | |
| 705 return kModelTypeInfoMap[model_type].root_tag; | |
| 706 } | |
| 707 | |
| 708 bool RealModelTypeToNotificationType(ModelType model_type, | |
| 709 std::string* notification_type) { | |
| 710 if (ProtocolTypes().Has(model_type)) { | |
| 711 *notification_type = kModelTypeInfoMap[model_type].notification_type; | |
| 712 return true; | |
| 713 } | |
| 714 notification_type->clear(); | |
| 715 return false; | |
| 716 } | |
| 717 | |
| 718 bool NotificationTypeToRealModelType(const std::string& notification_type, | |
| 719 ModelType* model_type) { | |
| 720 if (notification_type.empty()) { | |
| 721 *model_type = UNSPECIFIED; | |
| 722 return false; | |
| 723 } | |
| 724 for (size_t i = 0; i < arraysize(kModelTypeInfoMap); ++i) { | |
| 725 if (kModelTypeInfoMap[i].notification_type == notification_type) { | |
| 726 *model_type = kModelTypeInfoMap[i].model_type; | |
| 727 return true; | |
| 728 } | |
| 729 } | |
| 730 *model_type = UNSPECIFIED; | |
| 731 return false; | |
| 732 } | |
| 733 | |
| 734 bool IsRealDataType(ModelType model_type) { | |
| 735 return model_type >= FIRST_REAL_MODEL_TYPE && model_type < MODEL_TYPE_COUNT; | |
| 736 } | |
| 737 | |
| 738 bool IsProxyType(ModelType model_type) { | |
| 739 return model_type >= FIRST_PROXY_TYPE && model_type <= LAST_PROXY_TYPE; | |
| 740 } | |
| 741 | |
| 742 bool IsActOnceDataType(ModelType model_type) { | |
| 743 return model_type == HISTORY_DELETE_DIRECTIVES; | |
| 744 } | |
| 745 | |
| 746 bool IsTypeWithServerGeneratedRoot(ModelType model_type) { | |
| 747 return model_type == BOOKMARKS || model_type == NIGORI; | |
| 748 } | |
| 749 | |
| 750 bool IsTypeWithClientGeneratedRoot(ModelType model_type) { | |
| 751 return IsRealDataType(model_type) && | |
| 752 !IsTypeWithServerGeneratedRoot(model_type); | |
| 753 } | |
| 754 | |
| 755 bool TypeSupportsHierarchy(ModelType model_type) { | |
| 756 // TODO(stanisc): crbug/438313: Should this also include TOP_LEVEL_FOLDER? | |
| 757 return model_type == BOOKMARKS; | |
| 758 } | |
| 759 | |
| 760 bool TypeSupportsOrdering(ModelType model_type) { | |
| 761 return model_type == BOOKMARKS; | |
| 762 } | |
| 763 | |
| 764 } // namespace syncer | |
| OLD | NEW |