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