| 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 // Keep this file in sync with the .proto files in this directory. | |
| 6 | |
| 7 #include "sync/protocol/proto_value_conversions.h" | |
| 8 | |
| 9 #include <memory> | |
| 10 #include <string> | |
| 11 | |
| 12 #include "base/strings/string_number_conversions.h" | |
| 13 #include "base/time/time.h" | |
| 14 #include "base/values.h" | |
| 15 #include "sync/internal_api/public/base/model_type.h" | |
| 16 #include "sync/protocol/app_notification_specifics.pb.h" | |
| 17 #include "sync/protocol/app_setting_specifics.pb.h" | |
| 18 #include "sync/protocol/app_specifics.pb.h" | |
| 19 #include "sync/protocol/autofill_specifics.pb.h" | |
| 20 #include "sync/protocol/bookmark_specifics.pb.h" | |
| 21 #include "sync/protocol/device_info_specifics.pb.h" | |
| 22 #include "sync/protocol/encryption.pb.h" | |
| 23 #include "sync/protocol/experiments_specifics.pb.h" | |
| 24 #include "sync/protocol/extension_setting_specifics.pb.h" | |
| 25 #include "sync/protocol/extension_specifics.pb.h" | |
| 26 #include "sync/protocol/favicon_image_specifics.pb.h" | |
| 27 #include "sync/protocol/favicon_tracking_specifics.pb.h" | |
| 28 #include "sync/protocol/managed_user_setting_specifics.pb.h" | |
| 29 #include "sync/protocol/managed_user_shared_setting_specifics.pb.h" | |
| 30 #include "sync/protocol/managed_user_specifics.pb.h" | |
| 31 #include "sync/protocol/managed_user_whitelist_specifics.pb.h" | |
| 32 #include "sync/protocol/nigori_specifics.pb.h" | |
| 33 #include "sync/protocol/password_specifics.pb.h" | |
| 34 #include "sync/protocol/preference_specifics.pb.h" | |
| 35 #include "sync/protocol/priority_preference_specifics.pb.h" | |
| 36 #include "sync/protocol/search_engine_specifics.pb.h" | |
| 37 #include "sync/protocol/session_specifics.pb.h" | |
| 38 #include "sync/protocol/sync.pb.h" | |
| 39 #include "sync/protocol/theme_specifics.pb.h" | |
| 40 #include "sync/protocol/typed_url_specifics.pb.h" | |
| 41 #include "sync/protocol/wifi_credential_specifics.pb.h" | |
| 42 #include "testing/gtest/include/gtest/gtest.h" | |
| 43 | |
| 44 namespace syncer { | |
| 45 namespace { | |
| 46 | |
| 47 class ProtoValueConversionsTest : public testing::Test { | |
| 48 protected: | |
| 49 template <class T> | |
| 50 void TestSpecificsToValue( | |
| 51 std::unique_ptr<base::DictionaryValue> (*specifics_to_value)(const T&)) { | |
| 52 const T& specifics(T::default_instance()); | |
| 53 std::unique_ptr<base::DictionaryValue> value = | |
| 54 specifics_to_value(specifics); | |
| 55 // We can't do much but make sure that this doesn't crash. | |
| 56 } | |
| 57 }; | |
| 58 | |
| 59 TEST_F(ProtoValueConversionsTest, ProtoChangeCheck) { | |
| 60 // If this number changes, that means we added or removed a data | |
| 61 // type. Don't forget to add a unit test for {New | |
| 62 // type}SpecificsToValue below. | |
| 63 EXPECT_EQ(37, MODEL_TYPE_COUNT); | |
| 64 | |
| 65 // We'd also like to check if we changed any field in our messages. | |
| 66 // However, that's hard to do: sizeof could work, but it's | |
| 67 // platform-dependent. default_instance().ByteSize() won't change | |
| 68 // for most changes, since most of our fields are optional. So we | |
| 69 // just settle for comments in the proto files. | |
| 70 } | |
| 71 | |
| 72 TEST_F(ProtoValueConversionsTest, EncryptedDataToValue) { | |
| 73 TestSpecificsToValue(EncryptedDataToValue); | |
| 74 } | |
| 75 | |
| 76 TEST_F(ProtoValueConversionsTest, SessionHeaderToValue) { | |
| 77 TestSpecificsToValue(SessionHeaderToValue); | |
| 78 } | |
| 79 | |
| 80 TEST_F(ProtoValueConversionsTest, SessionTabToValue) { | |
| 81 TestSpecificsToValue(SessionTabToValue); | |
| 82 } | |
| 83 | |
| 84 TEST_F(ProtoValueConversionsTest, SessionWindowToValue) { | |
| 85 TestSpecificsToValue(SessionWindowToValue); | |
| 86 } | |
| 87 | |
| 88 TEST_F(ProtoValueConversionsTest, TabNavigationToValue) { | |
| 89 TestSpecificsToValue(TabNavigationToValue); | |
| 90 } | |
| 91 | |
| 92 TEST_F(ProtoValueConversionsTest, NavigationRedirectToValue) { | |
| 93 TestSpecificsToValue(NavigationRedirectToValue); | |
| 94 } | |
| 95 | |
| 96 TEST_F(ProtoValueConversionsTest, PasswordSpecificsData) { | |
| 97 sync_pb::PasswordSpecificsData specifics; | |
| 98 specifics.set_password_value("secret"); | |
| 99 std::unique_ptr<base::DictionaryValue> value( | |
| 100 PasswordSpecificsDataToValue(specifics)); | |
| 101 EXPECT_FALSE(value->empty()); | |
| 102 std::string password_value; | |
| 103 EXPECT_TRUE(value->GetString("password_value", &password_value)); | |
| 104 EXPECT_EQ("<redacted>", password_value); | |
| 105 } | |
| 106 | |
| 107 TEST_F(ProtoValueConversionsTest, AppListSpecificsToValue) { | |
| 108 TestSpecificsToValue(AppListSpecificsToValue); | |
| 109 } | |
| 110 | |
| 111 TEST_F(ProtoValueConversionsTest, AppNotificationToValue) { | |
| 112 TestSpecificsToValue(AppNotificationToValue); | |
| 113 } | |
| 114 | |
| 115 TEST_F(ProtoValueConversionsTest, AppSettingSpecificsToValue) { | |
| 116 sync_pb::AppNotificationSettings specifics; | |
| 117 specifics.set_disabled(true); | |
| 118 specifics.set_oauth_client_id("some_id_value"); | |
| 119 std::unique_ptr<base::DictionaryValue> value(AppSettingsToValue(specifics)); | |
| 120 EXPECT_FALSE(value->empty()); | |
| 121 bool disabled_value = false; | |
| 122 std::string oauth_client_id_value; | |
| 123 EXPECT_TRUE(value->GetBoolean("disabled", &disabled_value)); | |
| 124 EXPECT_EQ(true, disabled_value); | |
| 125 EXPECT_TRUE(value->GetString("oauth_client_id", &oauth_client_id_value)); | |
| 126 EXPECT_EQ("some_id_value", oauth_client_id_value); | |
| 127 } | |
| 128 | |
| 129 TEST_F(ProtoValueConversionsTest, AppSpecificsToValue) { | |
| 130 TestSpecificsToValue(AppSpecificsToValue); | |
| 131 } | |
| 132 | |
| 133 TEST_F(ProtoValueConversionsTest, ArcPackageSpecificsToValue) { | |
| 134 TestSpecificsToValue(ArcPackageSpecificsToValue); | |
| 135 } | |
| 136 | |
| 137 TEST_F(ProtoValueConversionsTest, AutofillSpecificsToValue) { | |
| 138 TestSpecificsToValue(AutofillSpecificsToValue); | |
| 139 } | |
| 140 | |
| 141 TEST_F(ProtoValueConversionsTest, AutofillProfileSpecificsToValue) { | |
| 142 TestSpecificsToValue(AutofillProfileSpecificsToValue); | |
| 143 } | |
| 144 | |
| 145 TEST_F(ProtoValueConversionsTest, AutofillWalletSpecificsToValue) { | |
| 146 TestSpecificsToValue(AutofillWalletSpecificsToValue); | |
| 147 } | |
| 148 | |
| 149 TEST_F(ProtoValueConversionsTest, WalletMetadataSpecificsToValue) { | |
| 150 TestSpecificsToValue(WalletMetadataSpecificsToValue); | |
| 151 } | |
| 152 | |
| 153 TEST_F(ProtoValueConversionsTest, BookmarkSpecificsToValue) { | |
| 154 TestSpecificsToValue(BookmarkSpecificsToValue); | |
| 155 } | |
| 156 | |
| 157 TEST_F(ProtoValueConversionsTest, BookmarkSpecificsData) { | |
| 158 const base::Time creation_time(base::Time::Now()); | |
| 159 const std::string icon_url = "http://www.google.com/favicon.ico"; | |
| 160 sync_pb::BookmarkSpecifics specifics; | |
| 161 specifics.set_creation_time_us(creation_time.ToInternalValue()); | |
| 162 specifics.set_icon_url(icon_url); | |
| 163 sync_pb::MetaInfo* meta_1 = specifics.add_meta_info(); | |
| 164 meta_1->set_key("key1"); | |
| 165 meta_1->set_value("value1"); | |
| 166 sync_pb::MetaInfo* meta_2 = specifics.add_meta_info(); | |
| 167 meta_2->set_key("key2"); | |
| 168 meta_2->set_value("value2"); | |
| 169 | |
| 170 std::unique_ptr<base::DictionaryValue> value( | |
| 171 BookmarkSpecificsToValue(specifics)); | |
| 172 EXPECT_FALSE(value->empty()); | |
| 173 std::string encoded_time; | |
| 174 EXPECT_TRUE(value->GetString("creation_time_us", &encoded_time)); | |
| 175 EXPECT_EQ(base::Int64ToString(creation_time.ToInternalValue()), encoded_time); | |
| 176 std::string encoded_icon_url; | |
| 177 EXPECT_TRUE(value->GetString("icon_url", &encoded_icon_url)); | |
| 178 EXPECT_EQ(icon_url, encoded_icon_url); | |
| 179 base::ListValue* meta_info_list; | |
| 180 ASSERT_TRUE(value->GetList("meta_info", &meta_info_list)); | |
| 181 EXPECT_EQ(2u, meta_info_list->GetSize()); | |
| 182 base::DictionaryValue* meta_info; | |
| 183 std::string meta_key; | |
| 184 std::string meta_value; | |
| 185 ASSERT_TRUE(meta_info_list->GetDictionary(0, &meta_info)); | |
| 186 EXPECT_TRUE(meta_info->GetString("key", &meta_key)); | |
| 187 EXPECT_TRUE(meta_info->GetString("value", &meta_value)); | |
| 188 EXPECT_EQ("key1", meta_key); | |
| 189 EXPECT_EQ("value1", meta_value); | |
| 190 ASSERT_TRUE(meta_info_list->GetDictionary(1, &meta_info)); | |
| 191 EXPECT_TRUE(meta_info->GetString("key", &meta_key)); | |
| 192 EXPECT_TRUE(meta_info->GetString("value", &meta_value)); | |
| 193 EXPECT_EQ("key2", meta_key); | |
| 194 EXPECT_EQ("value2", meta_value); | |
| 195 } | |
| 196 | |
| 197 TEST_F(ProtoValueConversionsTest, LinkedAppIconInfoToValue) { | |
| 198 TestSpecificsToValue(LinkedAppIconInfoToValue); | |
| 199 } | |
| 200 | |
| 201 TEST_F(ProtoValueConversionsTest, PriorityPreferenceSpecificsToValue) { | |
| 202 TestSpecificsToValue(PriorityPreferenceSpecificsToValue); | |
| 203 } | |
| 204 | |
| 205 TEST_F(ProtoValueConversionsTest, DeviceInfoSpecificsToValue) { | |
| 206 TestSpecificsToValue(DeviceInfoSpecificsToValue); | |
| 207 } | |
| 208 | |
| 209 TEST_F(ProtoValueConversionsTest, ExperimentsSpecificsToValue) { | |
| 210 TestSpecificsToValue(ExperimentsSpecificsToValue); | |
| 211 } | |
| 212 | |
| 213 TEST_F(ProtoValueConversionsTest, ExtensionSettingSpecificsToValue) { | |
| 214 TestSpecificsToValue(ExtensionSettingSpecificsToValue); | |
| 215 } | |
| 216 | |
| 217 TEST_F(ProtoValueConversionsTest, ExtensionSpecificsToValue) { | |
| 218 TestSpecificsToValue(ExtensionSpecificsToValue); | |
| 219 } | |
| 220 | |
| 221 TEST_F(ProtoValueConversionsTest, FaviconImageSpecificsToValue) { | |
| 222 TestSpecificsToValue(FaviconImageSpecificsToValue); | |
| 223 } | |
| 224 | |
| 225 TEST_F(ProtoValueConversionsTest, FaviconTrackingSpecificsToValue) { | |
| 226 TestSpecificsToValue(FaviconTrackingSpecificsToValue); | |
| 227 } | |
| 228 | |
| 229 TEST_F(ProtoValueConversionsTest, HistoryDeleteDirectiveSpecificsToValue) { | |
| 230 TestSpecificsToValue(HistoryDeleteDirectiveSpecificsToValue); | |
| 231 } | |
| 232 | |
| 233 TEST_F(ProtoValueConversionsTest, ManagedUserSettingSpecificsToValue) { | |
| 234 TestSpecificsToValue(ManagedUserSettingSpecificsToValue); | |
| 235 } | |
| 236 | |
| 237 TEST_F(ProtoValueConversionsTest, ManagedUserSpecificsToValue) { | |
| 238 TestSpecificsToValue(ManagedUserSpecificsToValue); | |
| 239 } | |
| 240 | |
| 241 TEST_F(ProtoValueConversionsTest, ManagedUserSharedSettingSpecificsToValue) { | |
| 242 TestSpecificsToValue(ManagedUserSharedSettingSpecificsToValue); | |
| 243 } | |
| 244 | |
| 245 TEST_F(ProtoValueConversionsTest, ManagedUserWhitelistSpecificsToValue) { | |
| 246 TestSpecificsToValue(ManagedUserWhitelistSpecificsToValue); | |
| 247 } | |
| 248 | |
| 249 TEST_F(ProtoValueConversionsTest, NigoriSpecificsToValue) { | |
| 250 TestSpecificsToValue(NigoriSpecificsToValue); | |
| 251 } | |
| 252 | |
| 253 TEST_F(ProtoValueConversionsTest, PasswordSpecificsToValue) { | |
| 254 TestSpecificsToValue(PasswordSpecificsToValue); | |
| 255 } | |
| 256 | |
| 257 TEST_F(ProtoValueConversionsTest, PreferenceSpecificsToValue) { | |
| 258 TestSpecificsToValue(PreferenceSpecificsToValue); | |
| 259 } | |
| 260 | |
| 261 TEST_F(ProtoValueConversionsTest, SearchEngineSpecificsToValue) { | |
| 262 TestSpecificsToValue(SearchEngineSpecificsToValue); | |
| 263 } | |
| 264 | |
| 265 TEST_F(ProtoValueConversionsTest, SessionSpecificsToValue) { | |
| 266 TestSpecificsToValue(SessionSpecificsToValue); | |
| 267 } | |
| 268 | |
| 269 TEST_F(ProtoValueConversionsTest, SyncedNotificationAppInfoSpecificsToValue) { | |
| 270 TestSpecificsToValue(SyncedNotificationAppInfoSpecificsToValue); | |
| 271 } | |
| 272 | |
| 273 TEST_F(ProtoValueConversionsTest, SyncedNotificationSpecificsToValue) { | |
| 274 TestSpecificsToValue(SyncedNotificationSpecificsToValue); | |
| 275 } | |
| 276 | |
| 277 TEST_F(ProtoValueConversionsTest, ThemeSpecificsToValue) { | |
| 278 TestSpecificsToValue(ThemeSpecificsToValue); | |
| 279 } | |
| 280 | |
| 281 TEST_F(ProtoValueConversionsTest, TypedUrlSpecificsToValue) { | |
| 282 TestSpecificsToValue(TypedUrlSpecificsToValue); | |
| 283 } | |
| 284 | |
| 285 TEST_F(ProtoValueConversionsTest, DictionarySpecificsToValue) { | |
| 286 TestSpecificsToValue(DictionarySpecificsToValue); | |
| 287 } | |
| 288 | |
| 289 TEST_F(ProtoValueConversionsTest, ArticleSpecificsToValue) { | |
| 290 TestSpecificsToValue(ArticleSpecificsToValue); | |
| 291 } | |
| 292 | |
| 293 TEST_F(ProtoValueConversionsTest, WifiCredentialSpecificsToValue) { | |
| 294 TestSpecificsToValue(WifiCredentialSpecificsToValue); | |
| 295 } | |
| 296 | |
| 297 // TODO(akalin): Figure out how to better test EntitySpecificsToValue. | |
| 298 | |
| 299 TEST_F(ProtoValueConversionsTest, EntitySpecificsToValue) { | |
| 300 sync_pb::EntitySpecifics specifics; | |
| 301 // Touch the extensions to make sure it shows up in the generated | |
| 302 // value. | |
| 303 #define SET_FIELD(key) (void)specifics.mutable_##key() | |
| 304 | |
| 305 SET_FIELD(app); | |
| 306 SET_FIELD(app_list); | |
| 307 SET_FIELD(app_notification); | |
| 308 SET_FIELD(app_setting); | |
| 309 SET_FIELD(arc_package); | |
| 310 SET_FIELD(article); | |
| 311 SET_FIELD(autofill); | |
| 312 SET_FIELD(autofill_profile); | |
| 313 SET_FIELD(bookmark); | |
| 314 SET_FIELD(device_info); | |
| 315 SET_FIELD(dictionary); | |
| 316 SET_FIELD(experiments); | |
| 317 SET_FIELD(extension); | |
| 318 SET_FIELD(extension_setting); | |
| 319 SET_FIELD(favicon_image); | |
| 320 SET_FIELD(favicon_tracking); | |
| 321 SET_FIELD(history_delete_directive); | |
| 322 SET_FIELD(managed_user_setting); | |
| 323 SET_FIELD(managed_user_shared_setting); | |
| 324 SET_FIELD(managed_user_whitelist); | |
| 325 SET_FIELD(managed_user); | |
| 326 SET_FIELD(nigori); | |
| 327 SET_FIELD(password); | |
| 328 SET_FIELD(preference); | |
| 329 SET_FIELD(priority_preference); | |
| 330 SET_FIELD(search_engine); | |
| 331 SET_FIELD(session); | |
| 332 SET_FIELD(synced_notification); | |
| 333 SET_FIELD(synced_notification_app_info); | |
| 334 SET_FIELD(theme); | |
| 335 SET_FIELD(typed_url); | |
| 336 SET_FIELD(wifi_credential); | |
| 337 SET_FIELD(autofill_wallet); | |
| 338 SET_FIELD(wallet_metadata); | |
| 339 | |
| 340 #undef SET_FIELD | |
| 341 | |
| 342 std::unique_ptr<base::DictionaryValue> value( | |
| 343 EntitySpecificsToValue(specifics)); | |
| 344 EXPECT_EQ(MODEL_TYPE_COUNT - FIRST_REAL_MODEL_TYPE - | |
| 345 (LAST_PROXY_TYPE - FIRST_PROXY_TYPE + 1), | |
| 346 static_cast<int>(value->size())); | |
| 347 } | |
| 348 | |
| 349 namespace { | |
| 350 // Returns whether the given value has specifics under the entries in the given | |
| 351 // path. | |
| 352 bool ValueHasSpecifics(const base::DictionaryValue& value, | |
| 353 const std::string& path) { | |
| 354 const base::ListValue* entities_list = NULL; | |
| 355 const base::DictionaryValue* entry_dictionary = NULL; | |
| 356 const base::DictionaryValue* specifics_dictionary = NULL; | |
| 357 | |
| 358 if (!value.GetList(path, &entities_list)) | |
| 359 return false; | |
| 360 | |
| 361 if (!entities_list->GetDictionary(0, &entry_dictionary)) | |
| 362 return false; | |
| 363 | |
| 364 return entry_dictionary->GetDictionary("specifics", | |
| 365 &specifics_dictionary); | |
| 366 } | |
| 367 } // namespace | |
| 368 | |
| 369 // Create a ClientToServerMessage with an EntitySpecifics. Converting it to | |
| 370 // a value should respect the |include_specifics| flag. | |
| 371 TEST_F(ProtoValueConversionsTest, ClientToServerMessageToValue) { | |
| 372 sync_pb::ClientToServerMessage message; | |
| 373 sync_pb::CommitMessage* commit_message = message.mutable_commit(); | |
| 374 sync_pb::SyncEntity* entity = commit_message->add_entries(); | |
| 375 entity->mutable_specifics(); | |
| 376 | |
| 377 std::unique_ptr<base::DictionaryValue> value_with_specifics( | |
| 378 ClientToServerMessageToValue(message, true /* include_specifics */)); | |
| 379 EXPECT_FALSE(value_with_specifics->empty()); | |
| 380 EXPECT_TRUE(ValueHasSpecifics(*(value_with_specifics.get()), | |
| 381 "commit.entries")); | |
| 382 | |
| 383 std::unique_ptr<base::DictionaryValue> value_without_specifics( | |
| 384 ClientToServerMessageToValue(message, false /* include_specifics */)); | |
| 385 EXPECT_FALSE(value_without_specifics->empty()); | |
| 386 EXPECT_FALSE(ValueHasSpecifics(*(value_without_specifics.get()), | |
| 387 "commit.entries")); | |
| 388 } | |
| 389 | |
| 390 // Create a ClientToServerResponse with an EntitySpecifics. Converting it to | |
| 391 // a value should respect the |include_specifics| flag. | |
| 392 TEST_F(ProtoValueConversionsTest, ClientToServerResponseToValue) { | |
| 393 sync_pb::ClientToServerResponse message; | |
| 394 sync_pb::GetUpdatesResponse* response = message.mutable_get_updates(); | |
| 395 sync_pb::SyncEntity* entity = response->add_entries(); | |
| 396 entity->mutable_specifics(); | |
| 397 | |
| 398 std::unique_ptr<base::DictionaryValue> value_with_specifics( | |
| 399 ClientToServerResponseToValue(message, true /* include_specifics */)); | |
| 400 EXPECT_FALSE(value_with_specifics->empty()); | |
| 401 EXPECT_TRUE(ValueHasSpecifics(*(value_with_specifics.get()), | |
| 402 "get_updates.entries")); | |
| 403 | |
| 404 std::unique_ptr<base::DictionaryValue> value_without_specifics( | |
| 405 ClientToServerResponseToValue(message, false /* include_specifics */)); | |
| 406 EXPECT_FALSE(value_without_specifics->empty()); | |
| 407 EXPECT_FALSE(ValueHasSpecifics(*(value_without_specifics.get()), | |
| 408 "get_updates.entries")); | |
| 409 } | |
| 410 | |
| 411 TEST_F(ProtoValueConversionsTest, AttachmentIdProtoToValue) { | |
| 412 TestSpecificsToValue(AttachmentIdProtoToValue); | |
| 413 } | |
| 414 | |
| 415 } // namespace | |
| 416 } // namespace syncer | |
| OLD | NEW |