blob: 3ef7bac67f48b629cede84a5a5a86ed19dbaed00 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sync/internal_api/public/base/model_type.h"
#include "base/strings/string_split.h"
#include "base/values.h"
#include "sync/protocol/app_notification_specifics.pb.h"
#include "sync/protocol/app_setting_specifics.pb.h"
#include "sync/protocol/app_specifics.pb.h"
#include "sync/protocol/autofill_specifics.pb.h"
#include "sync/protocol/bookmark_specifics.pb.h"
#include "sync/protocol/extension_setting_specifics.pb.h"
#include "sync/protocol/extension_specifics.pb.h"
#include "sync/protocol/nigori_specifics.pb.h"
#include "sync/protocol/password_specifics.pb.h"
#include "sync/protocol/preference_specifics.pb.h"
#include "sync/protocol/search_engine_specifics.pb.h"
#include "sync/protocol/session_specifics.pb.h"
#include "sync/protocol/sync.pb.h"
#include "sync/protocol/theme_specifics.pb.h"
#include "sync/protocol/typed_url_specifics.pb.h"
#include "sync/syncable/syncable_proto_util.h"
namespace syncer {
// Notes:
// 1) This list must contain exactly the same elements as the set returned by
// UserSelectableTypes().
// 2) This list must be in the same order as the respective values in the
// ModelType enum.
const char* kUserSelectableDataTypeNames[] = {
"bookmarks",
"preferences",
"passwords",
"autofill",
"themes",
"typedUrls",
"extensions",
"apps",
"wifiCredentials",
"tabs",
};
static_assert(
36 == MODEL_TYPE_COUNT,
"update kUserSelectableDataTypeName to match UserSelectableTypes");
void AddDefaultFieldValue(ModelType datatype,
sync_pb::EntitySpecifics* specifics) {
if (!ProtocolTypes().Has(datatype)) {
NOTREACHED() << "Only protocol types have field values.";
return;
}
switch (datatype) {
case BOOKMARKS:
specifics->mutable_bookmark();
break;
case PASSWORDS:
specifics->mutable_password();
break;
case PREFERENCES:
specifics->mutable_preference();
break;
case AUTOFILL:
specifics->mutable_autofill();
break;
case AUTOFILL_PROFILE:
specifics->mutable_autofill_profile();
break;
case AUTOFILL_WALLET_DATA:
specifics->mutable_autofill_wallet();
break;
case AUTOFILL_WALLET_METADATA:
specifics->mutable_wallet_metadata();
break;
case THEMES:
specifics->mutable_theme();
break;
case TYPED_URLS:
specifics->mutable_typed_url();
break;
case EXTENSIONS:
specifics->mutable_extension();
break;
case NIGORI:
specifics->mutable_nigori();
break;
case SEARCH_ENGINES:
specifics->mutable_search_engine();
break;
case SESSIONS:
specifics->mutable_session();
break;
case APPS:
specifics->mutable_app();
break;
case APP_LIST:
specifics->mutable_app_list();
break;
case APP_SETTINGS:
specifics->mutable_app_setting();
break;
case EXTENSION_SETTINGS:
specifics->mutable_extension_setting();
break;
case APP_NOTIFICATIONS:
specifics->mutable_app_notification();
break;
case HISTORY_DELETE_DIRECTIVES:
specifics->mutable_history_delete_directive();
break;
case SYNCED_NOTIFICATIONS:
specifics->mutable_synced_notification();
break;
case SYNCED_NOTIFICATION_APP_INFO:
specifics->mutable_synced_notification_app_info();
break;
case DEVICE_INFO:
specifics->mutable_device_info();
break;
case EXPERIMENTS:
specifics->mutable_experiments();
break;
case PRIORITY_PREFERENCES:
specifics->mutable_priority_preference();
break;
case DICTIONARY:
specifics->mutable_dictionary();
break;
case FAVICON_IMAGES:
specifics->mutable_favicon_image();
break;
case FAVICON_TRACKING:
specifics->mutable_favicon_tracking();
break;
case SUPERVISED_USER_SETTINGS:
specifics->mutable_managed_user_setting();
break;
case SUPERVISED_USERS:
specifics->mutable_managed_user();
break;
case SUPERVISED_USER_SHARED_SETTINGS:
specifics->mutable_managed_user_shared_setting();
break;
case SUPERVISED_USER_WHITELISTS:
specifics->mutable_managed_user_whitelist();
break;
case ARTICLES:
specifics->mutable_article();
break;
case WIFI_CREDENTIALS:
specifics->mutable_wifi_credential();
break;
default:
NOTREACHED() << "No known extension for model type.";
}
}
ModelType GetModelTypeFromSpecificsFieldNumber(int field_number) {
ModelTypeSet protocol_types = ProtocolTypes();
for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good();
iter.Inc()) {
if (GetSpecificsFieldNumberFromModelType(iter.Get()) == field_number)
return iter.Get();
}
return UNSPECIFIED;
}
int GetSpecificsFieldNumberFromModelType(ModelType model_type) {
DCHECK(ProtocolTypes().Has(model_type))
<< "Only protocol types have field values.";
switch (model_type) {
case BOOKMARKS:
return sync_pb::EntitySpecifics::kBookmarkFieldNumber;
case PASSWORDS:
return sync_pb::EntitySpecifics::kPasswordFieldNumber;
case PREFERENCES:
return sync_pb::EntitySpecifics::kPreferenceFieldNumber;
case AUTOFILL:
return sync_pb::EntitySpecifics::kAutofillFieldNumber;
case AUTOFILL_PROFILE:
return sync_pb::EntitySpecifics::kAutofillProfileFieldNumber;
case AUTOFILL_WALLET_DATA:
return sync_pb::EntitySpecifics::kAutofillWalletFieldNumber;
case AUTOFILL_WALLET_METADATA:
return sync_pb::EntitySpecifics::kWalletMetadataFieldNumber;
case THEMES:
return sync_pb::EntitySpecifics::kThemeFieldNumber;
case TYPED_URLS:
return sync_pb::EntitySpecifics::kTypedUrlFieldNumber;
case EXTENSIONS:
return sync_pb::EntitySpecifics::kExtensionFieldNumber;
case NIGORI:
return sync_pb::EntitySpecifics::kNigoriFieldNumber;
case SEARCH_ENGINES:
return sync_pb::EntitySpecifics::kSearchEngineFieldNumber;
case SESSIONS:
return sync_pb::EntitySpecifics::kSessionFieldNumber;
case APPS:
return sync_pb::EntitySpecifics::kAppFieldNumber;
case APP_LIST:
return sync_pb::EntitySpecifics::kAppListFieldNumber;
case APP_SETTINGS:
return sync_pb::EntitySpecifics::kAppSettingFieldNumber;
case EXTENSION_SETTINGS:
return sync_pb::EntitySpecifics::kExtensionSettingFieldNumber;
case APP_NOTIFICATIONS:
return sync_pb::EntitySpecifics::kAppNotificationFieldNumber;
case HISTORY_DELETE_DIRECTIVES:
return sync_pb::EntitySpecifics::kHistoryDeleteDirectiveFieldNumber;
case SYNCED_NOTIFICATIONS:
return sync_pb::EntitySpecifics::kSyncedNotificationFieldNumber;
case SYNCED_NOTIFICATION_APP_INFO:
return sync_pb::EntitySpecifics::kSyncedNotificationAppInfoFieldNumber;
case DEVICE_INFO:
return sync_pb::EntitySpecifics::kDeviceInfoFieldNumber;
case EXPERIMENTS:
return sync_pb::EntitySpecifics::kExperimentsFieldNumber;
case PRIORITY_PREFERENCES:
return sync_pb::EntitySpecifics::kPriorityPreferenceFieldNumber;
case DICTIONARY:
return sync_pb::EntitySpecifics::kDictionaryFieldNumber;
case FAVICON_IMAGES:
return sync_pb::EntitySpecifics::kFaviconImageFieldNumber;
case FAVICON_TRACKING:
return sync_pb::EntitySpecifics::kFaviconTrackingFieldNumber;
case SUPERVISED_USER_SETTINGS:
return sync_pb::EntitySpecifics::kManagedUserSettingFieldNumber;
case SUPERVISED_USERS:
return sync_pb::EntitySpecifics::kManagedUserFieldNumber;
case SUPERVISED_USER_SHARED_SETTINGS:
return sync_pb::EntitySpecifics::kManagedUserSharedSettingFieldNumber;
case SUPERVISED_USER_WHITELISTS:
return sync_pb::EntitySpecifics::kManagedUserWhitelistFieldNumber;
case ARTICLES:
return sync_pb::EntitySpecifics::kArticleFieldNumber;
case WIFI_CREDENTIALS:
return sync_pb::EntitySpecifics::kWifiCredentialFieldNumber;
default:
NOTREACHED() << "No known extension for model type.";
return 0;
}
}
FullModelTypeSet ToFullModelTypeSet(ModelTypeSet in) {
FullModelTypeSet out;
for (ModelTypeSet::Iterator i = in.First(); i.Good(); i.Inc()) {
out.Put(i.Get());
}
return out;
}
// Note: keep this consistent with GetModelType in entry.cc!
ModelType GetModelType(const sync_pb::SyncEntity& sync_entity) {
DCHECK(!IsRoot(sync_entity)); // Root shouldn't ever go over the wire.
// Backwards compatibility with old (pre-specifics) protocol.
if (sync_entity.has_bookmarkdata())
return BOOKMARKS;
ModelType specifics_type = GetModelTypeFromSpecifics(sync_entity.specifics());
if (specifics_type != UNSPECIFIED)
return specifics_type;
// Loose check for server-created top-level folders that aren't
// bound to a particular model type.
if (!sync_entity.server_defined_unique_tag().empty() &&
IsFolder(sync_entity)) {
return TOP_LEVEL_FOLDER;
}
// This is an item of a datatype we can't understand. Maybe it's
// from the future? Either we mis-encoded the object, or the
// server sent us entries it shouldn't have.
NOTREACHED() << "Unknown datatype in sync proto.";
return UNSPECIFIED;
}
ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics) {
if (specifics.has_bookmark())
return BOOKMARKS;
if (specifics.has_password())
return PASSWORDS;
if (specifics.has_preference())
return PREFERENCES;
if (specifics.has_autofill())
return AUTOFILL;
if (specifics.has_autofill_profile())
return AUTOFILL_PROFILE;
if (specifics.has_autofill_wallet())
return AUTOFILL_WALLET_DATA;
if (specifics.has_wallet_metadata())
return AUTOFILL_WALLET_METADATA;
if (specifics.has_theme())
return THEMES;
if (specifics.has_typed_url())
return TYPED_URLS;
if (specifics.has_extension())
return EXTENSIONS;
if (specifics.has_nigori())
return NIGORI;
if (specifics.has_app())
return APPS;
if (specifics.has_app_list())
return APP_LIST;
if (specifics.has_search_engine())
return SEARCH_ENGINES;
if (specifics.has_session())
return SESSIONS;
if (specifics.has_app_setting())
return APP_SETTINGS;
if (specifics.has_extension_setting())
return EXTENSION_SETTINGS;
if (specifics.has_app_notification())
return APP_NOTIFICATIONS;
if (specifics.has_history_delete_directive())
return HISTORY_DELETE_DIRECTIVES;
if (specifics.has_synced_notification())
return SYNCED_NOTIFICATIONS;
if (specifics.has_synced_notification_app_info())
return SYNCED_NOTIFICATION_APP_INFO;
if (specifics.has_device_info())
return DEVICE_INFO;
if (specifics.has_experiments())
return EXPERIMENTS;
if (specifics.has_priority_preference())
return PRIORITY_PREFERENCES;
if (specifics.has_dictionary())
return DICTIONARY;
if (specifics.has_favicon_image())
return FAVICON_IMAGES;
if (specifics.has_favicon_tracking())
return FAVICON_TRACKING;
if (specifics.has_managed_user_setting())
return SUPERVISED_USER_SETTINGS;
if (specifics.has_managed_user())
return SUPERVISED_USERS;
if (specifics.has_managed_user_shared_setting())
return SUPERVISED_USER_SHARED_SETTINGS;
if (specifics.has_managed_user_whitelist())
return SUPERVISED_USER_WHITELISTS;
if (specifics.has_article())
return ARTICLES;
if (specifics.has_wifi_credential())
return WIFI_CREDENTIALS;
return UNSPECIFIED;
}
ModelTypeSet ProtocolTypes() {
ModelTypeSet set = ModelTypeSet::All();
set.RemoveAll(ProxyTypes());
return set;
}
ModelTypeSet UserTypes() {
ModelTypeSet set;
// TODO(sync): We should be able to build the actual enumset's internal
// bitset value here at compile time, rather than performing an iteration
// every time.
for (int i = FIRST_USER_MODEL_TYPE; i <= LAST_USER_MODEL_TYPE; ++i) {
set.Put(ModelTypeFromInt(i));
}
return set;
}
ModelTypeSet UserSelectableTypes() {
ModelTypeSet set;
// Although the order doesn't technically matter here, it's clearer to keep
// these in the same order as their definition in the ModelType enum.
set.Put(BOOKMARKS);
set.Put(PREFERENCES);
set.Put(PASSWORDS);
set.Put(AUTOFILL);
set.Put(THEMES);
set.Put(TYPED_URLS);
set.Put(EXTENSIONS);
set.Put(APPS);
set.Put(WIFI_CREDENTIALS);
set.Put(PROXY_TABS);
return set;
}
bool IsUserSelectableType(ModelType model_type) {
return UserSelectableTypes().Has(model_type);
}
ModelTypeNameMap GetUserSelectableTypeNameMap() {
ModelTypeNameMap type_names;
ModelTypeSet type_set = UserSelectableTypes();
ModelTypeSet::Iterator it = type_set.First();
DCHECK_EQ(arraysize(kUserSelectableDataTypeNames), type_set.Size());
for (size_t i = 0; i < arraysize(kUserSelectableDataTypeNames) && it.Good();
++i, it.Inc()) {
type_names[it.Get()] = kUserSelectableDataTypeNames[i];
}
return type_names;
}
ModelTypeSet EncryptableUserTypes() {
ModelTypeSet encryptable_user_types = UserTypes();
// We never encrypt history delete directives.
encryptable_user_types.Remove(HISTORY_DELETE_DIRECTIVES);
// Synced notifications are not encrypted since the server must see changes.
encryptable_user_types.Remove(SYNCED_NOTIFICATIONS);
// Synced Notification App Info does not have private data, so it is not
// encrypted.
encryptable_user_types.Remove(SYNCED_NOTIFICATION_APP_INFO);
// Device info data is not encrypted because it might be synced before
// encryption is ready.
encryptable_user_types.Remove(DEVICE_INFO);
// Priority preferences are not encrypted because they might be synced before
// encryption is ready.
encryptable_user_types.Remove(PRIORITY_PREFERENCES);
// Supervised user settings are not encrypted since they are set server-side.
encryptable_user_types.Remove(SUPERVISED_USER_SETTINGS);
// Supervised users are not encrypted since they are managed server-side.
encryptable_user_types.Remove(SUPERVISED_USERS);
// Supervised user shared settings are not encrypted since they are managed
// server-side and shared between manager and supervised user.
encryptable_user_types.Remove(SUPERVISED_USER_SHARED_SETTINGS);
// Supervised user whitelists are not encrypted since they are managed
// server-side.
encryptable_user_types.Remove(SUPERVISED_USER_WHITELISTS);
// Proxy types have no sync representation and are therefore not encrypted.
// Note however that proxy types map to one or more protocol types, which
// may or may not be encrypted themselves.
encryptable_user_types.RemoveAll(ProxyTypes());
// Wallet data is not encrypted since it actually originates on the server.
encryptable_user_types.Remove(AUTOFILL_WALLET_DATA);
return encryptable_user_types;
}
ModelTypeSet PriorityUserTypes() {
return ModelTypeSet(DEVICE_INFO, PRIORITY_PREFERENCES);
}
ModelTypeSet ControlTypes() {
ModelTypeSet set;
// TODO(sync): We should be able to build the actual enumset's internal
// bitset value here at compile time, rather than performing an iteration
// every time.
for (int i = FIRST_CONTROL_MODEL_TYPE; i <= LAST_CONTROL_MODEL_TYPE; ++i) {
set.Put(ModelTypeFromInt(i));
}
return set;
}
ModelTypeSet ProxyTypes() {
ModelTypeSet set;
set.Put(PROXY_TABS);
return set;
}
bool IsControlType(ModelType model_type) {
return ControlTypes().Has(model_type);
}
ModelTypeSet CoreTypes() {
syncer::ModelTypeSet result;
result.PutAll(PriorityCoreTypes());
// The following are low priority core types.
result.Put(SYNCED_NOTIFICATIONS);
result.Put(SYNCED_NOTIFICATION_APP_INFO);
result.Put(SUPERVISED_USER_SHARED_SETTINGS);
result.Put(SUPERVISED_USER_WHITELISTS);
return result;
}
ModelTypeSet PriorityCoreTypes() {
syncer::ModelTypeSet result;
result.PutAll(ControlTypes());
// The following are non-control core types.
result.Put(SUPERVISED_USERS);
result.Put(SUPERVISED_USER_SETTINGS);
return result;
}
ModelTypeSet BackupTypes() {
ModelTypeSet result;
result.Put(BOOKMARKS);
result.Put(PREFERENCES);
result.Put(THEMES);
result.Put(EXTENSIONS);
result.Put(SEARCH_ENGINES);
result.Put(APPS);
result.Put(APP_LIST);
result.Put(APP_SETTINGS);
result.Put(EXTENSION_SETTINGS);
result.Put(PRIORITY_PREFERENCES);
return result;
}
const char* ModelTypeToString(ModelType model_type) {
// This is used in serialization routines as well as for displaying debug
// information. Do not attempt to change these string values unless you know
// what you're doing.
switch (model_type) {
case TOP_LEVEL_FOLDER:
return "Top Level Folder";
case UNSPECIFIED:
return "Unspecified";
case BOOKMARKS:
return "Bookmarks";
case PREFERENCES:
return "Preferences";
case PASSWORDS:
return "Passwords";
case AUTOFILL:
return "Autofill";
case THEMES:
return "Themes";
case TYPED_URLS:
return "Typed URLs";
case EXTENSIONS:
return "Extensions";
case NIGORI:
return "Encryption keys";
case SEARCH_ENGINES:
return "Search Engines";
case SESSIONS:
return "Sessions";
case APPS:
return "Apps";
case APP_LIST:
return "App List";
case AUTOFILL_PROFILE:
return "Autofill Profiles";
case APP_SETTINGS:
return "App settings";
case EXTENSION_SETTINGS:
return "Extension settings";
case APP_NOTIFICATIONS:
return "App Notifications";
case HISTORY_DELETE_DIRECTIVES:
return "History Delete Directives";
case SYNCED_NOTIFICATIONS:
return "Synced Notifications";
case SYNCED_NOTIFICATION_APP_INFO:
return "Synced Notification App Info";
case DEVICE_INFO:
return "Device Info";
case EXPERIMENTS:
return "Experiments";
case PRIORITY_PREFERENCES:
return "Priority Preferences";
case DICTIONARY:
return "Dictionary";
case FAVICON_IMAGES:
return "Favicon Images";
case FAVICON_TRACKING:
return "Favicon Tracking";
case SUPERVISED_USER_SETTINGS:
return "Managed User Settings";
case SUPERVISED_USERS:
return "Managed Users";
case SUPERVISED_USER_SHARED_SETTINGS:
return "Managed User Shared Settings";
case SUPERVISED_USER_WHITELISTS:
return "Managed User Whitelists";
case ARTICLES:
return "Articles";
case WIFI_CREDENTIALS:
return "WiFi Credentials";
case PROXY_TABS:
return "Tabs";
case AUTOFILL_WALLET_DATA:
return "Autofill Wallet";
case AUTOFILL_WALLET_METADATA:
return "Autofill Wallet Metadata";
default:
break;
}
NOTREACHED() << "No known extension for model type.";
return "INVALID";
}
// The normal rules about histograms apply here. Always append to the bottom of
// the list, and be careful to not reuse integer values that have already been
// assigned.
//
// Don't forget to update the "SyncModelTypes" enum in histograms.xml when you
// make changes to this list.
int ModelTypeToHistogramInt(ModelType model_type) {
switch (model_type) {
case UNSPECIFIED:
return 0;
case TOP_LEVEL_FOLDER:
return 1;
case BOOKMARKS:
return 2;
case PREFERENCES:
return 3;
case PASSWORDS:
return 4;
case AUTOFILL_PROFILE:
return 5;
case AUTOFILL:
return 6;
case THEMES:
return 7;
case TYPED_URLS:
return 8;
case EXTENSIONS:
return 9;
case SEARCH_ENGINES:
return 10;
case SESSIONS:
return 11;
case APPS:
return 12;
case APP_SETTINGS:
return 13;
case EXTENSION_SETTINGS:
return 14;
case APP_NOTIFICATIONS:
return 15;
case HISTORY_DELETE_DIRECTIVES:
return 16;
case NIGORI:
return 17;
case DEVICE_INFO:
return 18;
case EXPERIMENTS:
return 19;
case SYNCED_NOTIFICATIONS:
return 20;
case PRIORITY_PREFERENCES:
return 21;
case DICTIONARY:
return 22;
case FAVICON_IMAGES:
return 23;
case FAVICON_TRACKING:
return 24;
case PROXY_TABS:
return 25;
case SUPERVISED_USER_SETTINGS:
return 26;
case SUPERVISED_USERS:
return 27;
case ARTICLES:
return 28;
case APP_LIST:
return 29;
case SUPERVISED_USER_SHARED_SETTINGS:
return 30;
case SYNCED_NOTIFICATION_APP_INFO:
return 31;
case WIFI_CREDENTIALS:
return 32;
case SUPERVISED_USER_WHITELISTS:
return 33;
case AUTOFILL_WALLET_DATA:
return 34;
case AUTOFILL_WALLET_METADATA:
return 35;
// Silence a compiler warning.
case MODEL_TYPE_COUNT:
return 0;
}
return 0;
}
base::StringValue* ModelTypeToValue(ModelType model_type) {
if (model_type >= FIRST_REAL_MODEL_TYPE) {
return new base::StringValue(ModelTypeToString(model_type));
} else if (model_type == TOP_LEVEL_FOLDER) {
return new base::StringValue("Top-level folder");
} else if (model_type == UNSPECIFIED) {
return new base::StringValue("Unspecified");
}
NOTREACHED();
return new base::StringValue(std::string());
}
ModelType ModelTypeFromValue(const base::Value& value) {
if (value.IsType(base::Value::TYPE_STRING)) {
std::string result;
CHECK(value.GetAsString(&result));
return ModelTypeFromString(result);
} else if (value.IsType(base::Value::TYPE_INTEGER)) {
int result;
CHECK(value.GetAsInteger(&result));
return ModelTypeFromInt(result);
} else {
NOTREACHED() << "Unsupported value type: " << value.GetType();
return UNSPECIFIED;
}
}
ModelType ModelTypeFromString(const std::string& model_type_string) {
if (model_type_string == "Bookmarks")
return BOOKMARKS;
else if (model_type_string == "Preferences")
return PREFERENCES;
else if (model_type_string == "Passwords")
return PASSWORDS;
else if (model_type_string == "Autofill")
return AUTOFILL;
else if (model_type_string == "Autofill Profiles")
return AUTOFILL_PROFILE;
else if (model_type_string == "Autofill Wallet")
return AUTOFILL_WALLET_DATA;
else if (model_type_string == "Autofill Wallet Metadata")
return AUTOFILL_WALLET_METADATA;
else if (model_type_string == "Themes")
return THEMES;
else if (model_type_string == "Typed URLs")
return TYPED_URLS;
else if (model_type_string == "Extensions")
return EXTENSIONS;
else if (model_type_string == "Encryption keys")
return NIGORI;
else if (model_type_string == "Search Engines")
return SEARCH_ENGINES;
else if (model_type_string == "Sessions")
return SESSIONS;
else if (model_type_string == "Apps")
return APPS;
else if (model_type_string == "App List")
return APP_LIST;
else if (model_type_string == "App settings")
return APP_SETTINGS;
else if (model_type_string == "Extension settings")
return EXTENSION_SETTINGS;
else if (model_type_string == "App Notifications")
return APP_NOTIFICATIONS;
else if (model_type_string == "History Delete Directives")
return HISTORY_DELETE_DIRECTIVES;
else if (model_type_string == "Synced Notifications")
return SYNCED_NOTIFICATIONS;
else if (model_type_string == "Synced Notification App Info")
return SYNCED_NOTIFICATION_APP_INFO;
else if (model_type_string == "Device Info")
return DEVICE_INFO;
else if (model_type_string == "Experiments")
return EXPERIMENTS;
else if (model_type_string == "Priority Preferences")
return PRIORITY_PREFERENCES;
else if (model_type_string == "Dictionary")
return DICTIONARY;
else if (model_type_string == "Favicon Images")
return FAVICON_IMAGES;
else if (model_type_string == "Favicon Tracking")
return FAVICON_TRACKING;
else if (model_type_string == "Managed User Settings")
return SUPERVISED_USER_SETTINGS;
else if (model_type_string == "Managed Users")
return SUPERVISED_USERS;
else if (model_type_string == "Managed User Shared Settings")
return SUPERVISED_USER_SHARED_SETTINGS;
else if (model_type_string == "Managed User Whitelists")
return SUPERVISED_USER_WHITELISTS;
else if (model_type_string == "Articles")
return ARTICLES;
else if (model_type_string == "WiFi Credentials")
return WIFI_CREDENTIALS;
else if (model_type_string == "Tabs")
return PROXY_TABS;
else
NOTREACHED() << "No known model type corresponding to "
<< model_type_string << ".";
return UNSPECIFIED;
}
std::string ModelTypeSetToString(ModelTypeSet model_types) {
std::string result;
for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) {
if (!result.empty()) {
result += ", ";
}
result += ModelTypeToString(it.Get());
}
return result;
}
ModelTypeSet ModelTypeSetFromString(const std::string& model_types_string) {
std::string working_copy = model_types_string;
ModelTypeSet model_types;
while (!working_copy.empty()) {
// Remove any leading spaces.
working_copy = working_copy.substr(working_copy.find_first_not_of(' '));
if (working_copy.empty())
break;
std::string type_str;
size_t end = working_copy.find(',');
if (end == std::string::npos) {
end = working_copy.length() - 1;
type_str = working_copy;
} else {
type_str = working_copy.substr(0, end);
}
syncer::ModelType type = ModelTypeFromString(type_str);
if (IsRealDataType(type))
model_types.Put(type);
working_copy = working_copy.substr(end + 1);
}
return model_types;
}
scoped_ptr<base::ListValue> ModelTypeSetToValue(ModelTypeSet model_types) {
scoped_ptr<base::ListValue> value(new base::ListValue());
for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) {
value->AppendString(ModelTypeToString(it.Get()));
}
return value;
}
ModelTypeSet ModelTypeSetFromValue(const base::ListValue& value) {
ModelTypeSet result;
for (base::ListValue::const_iterator i = value.begin();
i != value.end(); ++i) {
result.Put(ModelTypeFromValue(**i));
}
return result;
}
// TODO(zea): remove all hardcoded tags in model associators and have them use
// this instead.
// NOTE: Proxy types should return empty strings (so that we don't NOTREACHED
// in tests when we verify they have no root node).
std::string ModelTypeToRootTag(ModelType type) {
switch (type) {
case BOOKMARKS:
return "google_chrome_bookmarks";
case PREFERENCES:
return "google_chrome_preferences";
case PASSWORDS:
return "google_chrome_passwords";
case AUTOFILL:
return "google_chrome_autofill";
case THEMES:
return "google_chrome_themes";
case TYPED_URLS:
return "google_chrome_typed_urls";
case EXTENSIONS:
return "google_chrome_extensions";
case NIGORI:
return "google_chrome_nigori";
case SEARCH_ENGINES:
return "google_chrome_search_engines";
case SESSIONS:
return "google_chrome_sessions";
case APPS:
return "google_chrome_apps";
case APP_LIST:
return "google_chrome_app_list";
case AUTOFILL_PROFILE:
return "google_chrome_autofill_profiles";
case AUTOFILL_WALLET_DATA:
return "google_chrome_autofill_wallet";
case AUTOFILL_WALLET_METADATA:
return "google_chrome_autofill_wallet_metadata";
case APP_SETTINGS:
return "google_chrome_app_settings";
case EXTENSION_SETTINGS:
return "google_chrome_extension_settings";
case APP_NOTIFICATIONS:
return "google_chrome_app_notifications";
case HISTORY_DELETE_DIRECTIVES:
return "google_chrome_history_delete_directives";
case SYNCED_NOTIFICATIONS:
return "google_chrome_synced_notifications";
case SYNCED_NOTIFICATION_APP_INFO:
return "google_chrome_synced_notification_app_info";
case DEVICE_INFO:
return "google_chrome_device_info";
case EXPERIMENTS:
return "google_chrome_experiments";
case PRIORITY_PREFERENCES:
return "google_chrome_priority_preferences";
case DICTIONARY:
return "google_chrome_dictionary";
case FAVICON_IMAGES:
return "google_chrome_favicon_images";
case FAVICON_TRACKING:
return "google_chrome_favicon_tracking";
case SUPERVISED_USER_SETTINGS:
return "google_chrome_managed_user_settings";
case SUPERVISED_USERS:
return "google_chrome_managed_users";
case SUPERVISED_USER_SHARED_SETTINGS:
return "google_chrome_managed_user_shared_settings";
case SUPERVISED_USER_WHITELISTS:
return "google_chrome_managed_user_whitelists";
case ARTICLES:
return "google_chrome_articles";
case WIFI_CREDENTIALS:
return "google_chrome_wifi_credentials";
case PROXY_TABS:
return std::string();
default:
break;
}
NOTREACHED() << "No known extension for model type.";
return "INVALID";
}
// TODO(akalin): Figure out a better way to do these mappings.
// Note: Do not include proxy types in this list. They should never receive
// or trigger notifications.
namespace {
const char kBookmarkNotificationType[] = "BOOKMARK";
const char kPreferenceNotificationType[] = "PREFERENCE";
const char kPasswordNotificationType[] = "PASSWORD";
const char kAutofillNotificationType[] = "AUTOFILL";
const char kThemeNotificationType[] = "THEME";
const char kTypedUrlNotificationType[] = "TYPED_URL";
const char kExtensionNotificationType[] = "EXTENSION";
const char kExtensionSettingNotificationType[] = "EXTENSION_SETTING";
const char kNigoriNotificationType[] = "NIGORI";
const char kAppSettingNotificationType[] = "APP_SETTING";
const char kAppNotificationType[] = "APP";
const char kAppListNotificationType[] = "APP_LIST";
const char kSearchEngineNotificationType[] = "SEARCH_ENGINE";
const char kSessionNotificationType[] = "SESSION";
const char kAutofillProfileNotificationType[] = "AUTOFILL_PROFILE";
const char kAutofillWalletMetadataNotificationType[] =
"AUTOFILL_WALLET_METADATA";
const char kAutofillWalletNotificationType[] = "AUTOFILL_WALLET";
const char kAppNotificationNotificationType[] = "APP_NOTIFICATION";
const char kHistoryDeleteDirectiveNotificationType[] =
"HISTORY_DELETE_DIRECTIVE";
const char kSyncedNotificationType[] = "SYNCED_NOTIFICATION";
const char kSyncedNotificationAppInfoType[] = "SYNCED_NOTIFICATION_APP_INFO";
const char kDeviceInfoNotificationType[] = "DEVICE_INFO";
const char kExperimentsNotificationType[] = "EXPERIMENTS";
const char kPriorityPreferenceNotificationType[] = "PRIORITY_PREFERENCE";
const char kDictionaryNotificationType[] = "DICTIONARY";
const char kFaviconImageNotificationType[] = "FAVICON_IMAGE";
const char kFaviconTrackingNotificationType[] = "FAVICON_TRACKING";
const char kSupervisedUserSettingNotificationType[] = "MANAGED_USER_SETTING";
const char kSupervisedUserNotificationType[] = "MANAGED_USER";
const char kSupervisedUserSharedSettingNotificationType[] =
"MANAGED_USER_SHARED_SETTING";
const char kSupervisedUserWhitelistNotificationType[] =
"MANAGED_USER_WHITELIST";
const char kArticleNotificationType[] = "ARTICLE";
const char kWifiCredentialNotificationType[] = "WIFI_CREDENTIAL";
} // namespace
bool RealModelTypeToNotificationType(ModelType model_type,
std::string* notification_type) {
switch (model_type) {
case BOOKMARKS:
*notification_type = kBookmarkNotificationType;
return true;
case PREFERENCES:
*notification_type = kPreferenceNotificationType;
return true;
case PASSWORDS:
*notification_type = kPasswordNotificationType;
return true;
case AUTOFILL:
*notification_type = kAutofillNotificationType;
return true;
case THEMES:
*notification_type = kThemeNotificationType;
return true;
case TYPED_URLS:
*notification_type = kTypedUrlNotificationType;
return true;
case EXTENSIONS:
*notification_type = kExtensionNotificationType;
return true;
case NIGORI:
*notification_type = kNigoriNotificationType;
return true;
case APP_SETTINGS:
*notification_type = kAppSettingNotificationType;
return true;
case APPS:
*notification_type = kAppNotificationType;
return true;
case APP_LIST:
*notification_type = kAppListNotificationType;
return true;
case SEARCH_ENGINES:
*notification_type = kSearchEngineNotificationType;
return true;
case SESSIONS:
*notification_type = kSessionNotificationType;
return true;
case AUTOFILL_PROFILE:
*notification_type = kAutofillProfileNotificationType;
return true;
case AUTOFILL_WALLET_DATA:
*notification_type = kAutofillWalletNotificationType;
return true;
case AUTOFILL_WALLET_METADATA:
*notification_type = kAutofillWalletMetadataNotificationType;
return true;
case EXTENSION_SETTINGS:
*notification_type = kExtensionSettingNotificationType;
return true;
case APP_NOTIFICATIONS:
*notification_type = kAppNotificationNotificationType;
return true;
case HISTORY_DELETE_DIRECTIVES:
*notification_type = kHistoryDeleteDirectiveNotificationType;
return true;
case SYNCED_NOTIFICATIONS:
*notification_type = kSyncedNotificationType;
return true;
case SYNCED_NOTIFICATION_APP_INFO:
*notification_type = kSyncedNotificationAppInfoType;
return true;
case DEVICE_INFO:
*notification_type = kDeviceInfoNotificationType;
return true;
case EXPERIMENTS:
*notification_type = kExperimentsNotificationType;
return true;
case PRIORITY_PREFERENCES:
*notification_type = kPriorityPreferenceNotificationType;
return true;
case DICTIONARY:
*notification_type = kDictionaryNotificationType;
return true;
case FAVICON_IMAGES:
*notification_type = kFaviconImageNotificationType;
return true;
case FAVICON_TRACKING:
*notification_type = kFaviconTrackingNotificationType;
return true;
case SUPERVISED_USER_SETTINGS:
*notification_type = kSupervisedUserSettingNotificationType;
return true;
case SUPERVISED_USERS:
*notification_type = kSupervisedUserNotificationType;
return true;
case SUPERVISED_USER_SHARED_SETTINGS:
*notification_type = kSupervisedUserSharedSettingNotificationType;
return true;
case SUPERVISED_USER_WHITELISTS:
*notification_type = kSupervisedUserWhitelistNotificationType;
return true;
case ARTICLES:
*notification_type = kArticleNotificationType;
return true;
case WIFI_CREDENTIALS:
*notification_type = kWifiCredentialNotificationType;
return true;
default:
break;
}
notification_type->clear();
return false;
}
bool NotificationTypeToRealModelType(const std::string& notification_type,
ModelType* model_type) {
if (notification_type == kBookmarkNotificationType) {
*model_type = BOOKMARKS;
return true;
} else if (notification_type == kPreferenceNotificationType) {
*model_type = PREFERENCES;
return true;
} else if (notification_type == kPasswordNotificationType) {
*model_type = PASSWORDS;
return true;
} else if (notification_type == kAutofillNotificationType) {
*model_type = AUTOFILL;
return true;
} else if (notification_type == kThemeNotificationType) {
*model_type = THEMES;
return true;
} else if (notification_type == kTypedUrlNotificationType) {
*model_type = TYPED_URLS;
return true;
} else if (notification_type == kExtensionNotificationType) {
*model_type = EXTENSIONS;
return true;
} else if (notification_type == kNigoriNotificationType) {
*model_type = NIGORI;
return true;
} else if (notification_type == kAppNotificationType) {
*model_type = APPS;
return true;
} else if (notification_type == kAppListNotificationType) {
*model_type = APP_LIST;
return true;
} else if (notification_type == kSearchEngineNotificationType) {
*model_type = SEARCH_ENGINES;
return true;
} else if (notification_type == kSessionNotificationType) {
*model_type = SESSIONS;
return true;
} else if (notification_type == kAutofillProfileNotificationType) {
*model_type = AUTOFILL_PROFILE;
return true;
} else if (notification_type == kAutofillWalletNotificationType) {
*model_type = AUTOFILL_WALLET_DATA;
return true;
} else if (notification_type == kAutofillWalletMetadataNotificationType) {
*model_type = AUTOFILL_WALLET_METADATA;
return true;
} else if (notification_type == kAppSettingNotificationType) {
*model_type = APP_SETTINGS;
return true;
} else if (notification_type == kExtensionSettingNotificationType) {
*model_type = EXTENSION_SETTINGS;
return true;
} else if (notification_type == kAppNotificationNotificationType) {
*model_type = APP_NOTIFICATIONS;
return true;
} else if (notification_type == kHistoryDeleteDirectiveNotificationType) {
*model_type = HISTORY_DELETE_DIRECTIVES;
return true;
} else if (notification_type == kSyncedNotificationType) {
*model_type = SYNCED_NOTIFICATIONS;
return true;
} else if (notification_type == kSyncedNotificationAppInfoType) {
*model_type = SYNCED_NOTIFICATION_APP_INFO;
return true;
} else if (notification_type == kDeviceInfoNotificationType) {
*model_type = DEVICE_INFO;
return true;
} else if (notification_type == kExperimentsNotificationType) {
*model_type = EXPERIMENTS;
return true;
} else if (notification_type == kPriorityPreferenceNotificationType) {
*model_type = PRIORITY_PREFERENCES;
return true;
} else if (notification_type == kDictionaryNotificationType) {
*model_type = DICTIONARY;
return true;
} else if (notification_type == kFaviconImageNotificationType) {
*model_type = FAVICON_IMAGES;
return true;
} else if (notification_type == kFaviconTrackingNotificationType) {
*model_type = FAVICON_TRACKING;
return true;
} else if (notification_type == kSupervisedUserSettingNotificationType) {
*model_type = SUPERVISED_USER_SETTINGS;
return true;
} else if (notification_type == kSupervisedUserNotificationType) {
*model_type = SUPERVISED_USERS;
return true;
} else if (notification_type ==
kSupervisedUserSharedSettingNotificationType) {
*model_type = SUPERVISED_USER_SHARED_SETTINGS;
return true;
} else if (notification_type == kSupervisedUserWhitelistNotificationType) {
*model_type = SUPERVISED_USER_WHITELISTS;
return true;
} else if (notification_type == kArticleNotificationType) {
*model_type = ARTICLES;
return true;
} else if (notification_type == kWifiCredentialNotificationType) {
*model_type = WIFI_CREDENTIALS;
return true;
}
*model_type = UNSPECIFIED;
return false;
}
bool IsRealDataType(ModelType model_type) {
return model_type >= FIRST_REAL_MODEL_TYPE && model_type < MODEL_TYPE_COUNT;
}
bool IsProxyType(ModelType model_type) {
return model_type >= FIRST_PROXY_TYPE && model_type <= LAST_PROXY_TYPE;
}
bool IsActOnceDataType(ModelType model_type) {
return model_type == HISTORY_DELETE_DIRECTIVES;
}
bool IsTypeWithServerGeneratedRoot(ModelType model_type) {
return model_type == BOOKMARKS || model_type == NIGORI;
}
bool IsTypeWithClientGeneratedRoot(ModelType model_type) {
return IsRealDataType(model_type) &&
!IsTypeWithServerGeneratedRoot(model_type);
}
bool TypeSupportsHierarchy(ModelType model_type) {
// TODO(stanisc): crbug/438313: Should this also include TOP_LEVEL_FOLDER?
return model_type == BOOKMARKS;
}
bool TypeSupportsOrdering(ModelType model_type) {
return model_type == BOOKMARKS;
}
} // namespace syncer