| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/macros.h" | 5 #include "base/macros.h" |
| 6 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" | 6 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" |
| 7 #include "chrome/browser/sync/test/integration/sync_test.h" | 7 #include "chrome/browser/sync/test/integration/sync_test.h" |
| 8 #include "components/browser_sync/profile_sync_service.h" | 8 #include "components/browser_sync/profile_sync_service.h" |
| 9 #include "components/sync/base/model_type.h" | 9 #include "components/sync/base/model_type.h" |
| 10 #include "components/sync/base/sync_prefs.h" |
| 10 #include "components/sync/driver/sync_driver_switches.h" | 11 #include "components/sync/driver/sync_driver_switches.h" |
| 11 #include "components/sync/syncable/read_node.h" | 12 #include "components/sync/syncable/read_node.h" |
| 12 #include "components/sync/syncable/read_transaction.h" | 13 #include "components/sync/syncable/read_transaction.h" |
| 13 | 14 |
| 14 // This file contains tests that exercise enabling and disabling data | 15 using base::FeatureList; |
| 15 // types. | 16 using syncer::ModelType; |
| 17 using syncer::ModelTypeSet; |
| 18 using syncer::ModelTypeToString; |
| 19 using syncer::ProxyTypes; |
| 20 using syncer::SyncPrefs; |
| 21 using syncer::UserSelectableTypes; |
| 22 using syncer::UserShare; |
| 16 | 23 |
| 17 namespace { | 24 namespace { |
| 18 | 25 |
| 19 using base::FeatureList; | 26 bool DoesTopLevelNodeExist(UserShare* user_share, ModelType type) { |
| 20 using syncer::ModelTypeSet; | 27 syncer::ReadTransaction trans(FROM_HERE, user_share); |
| 28 syncer::ReadNode node(&trans); |
| 29 return node.InitTypeRoot(type) == syncer::BaseNode::INIT_OK; |
| 30 } |
| 21 | 31 |
| 22 class EnableDisableSingleClientTest : public SyncTest { | 32 void VerifyExistence(UserShare* user_share, |
| 23 public: | 33 bool should_root_node_exist, |
| 24 EnableDisableSingleClientTest() : SyncTest(SINGLE_CLIENT) {} | 34 ModelType type) { |
| 25 ~EnableDisableSingleClientTest() override {} | 35 EXPECT_EQ(should_root_node_exist, DoesTopLevelNodeExist(user_share, type)) |
| 36 << ModelTypeToString(type); |
| 37 } |
| 26 | 38 |
| 27 // Don't use self-notifications as they can trigger additional sync cycles. | 39 void VerifyExistence(UserShare* user_share, |
| 28 bool TestUsesSelfNotifications() override { return false; } | 40 bool should_root_node_exist, |
| 29 | 41 ModelType grouped, |
| 30 private: | 42 ModelType selectable) { |
| 31 DISALLOW_COPY_AND_ASSIGN(EnableDisableSingleClientTest); | 43 EXPECT_EQ(should_root_node_exist, DoesTopLevelNodeExist(user_share, grouped)) |
| 32 }; | 44 << ModelTypeToString(selectable) << "->" << ModelTypeToString(grouped); |
| 33 | |
| 34 bool DoesTopLevelNodeExist(syncer::UserShare* user_share, | |
| 35 syncer::ModelType type) { | |
| 36 syncer::ReadTransaction trans(FROM_HERE, user_share); | |
| 37 syncer::ReadNode node(&trans); | |
| 38 return node.InitTypeRoot(type) == syncer::BaseNode::INIT_OK; | |
| 39 } | 45 } |
| 40 | 46 |
| 41 bool IsUnready(const syncer::DataTypeStatusTable& data_type_status_table, | 47 bool IsUnready(const syncer::DataTypeStatusTable& data_type_status_table, |
| 42 syncer::ModelType type) { | 48 ModelType type) { |
| 43 return data_type_status_table.GetUnreadyErrorTypes().Has(type); | 49 return data_type_status_table.GetUnreadyErrorTypes().Has(type); |
| 44 } | 50 } |
| 45 | 51 |
| 46 // The current approach this test class takes is to examine the Directory and | 52 // The current approach this test class takes is to examine the Directory and |
| 47 // check for root nodes to see if a type is currently enabled. While this works | 53 // check for root nodes to see if a type is currently enabled. While this works |
| 48 // for things in the directory, it does not work for USS types. USS does not | 54 // for things in the directory, it does not work for USS types. USS does not |
| 49 // have any general data access mechanism, at least yet. Until that exists, | 55 // have any general data access mechanism, at least yet. Until that exists, |
| 50 // simply omit types that may be USS from these cases. | 56 // simply omit types that may be USS from these cases. |
| 51 ModelTypeSet UnifiedSyncServiceTypes() { | 57 ModelTypeSet UnifiedSyncServiceTypes() { |
| 52 ModelTypeSet set; | 58 ModelTypeSet set; |
| 53 if (FeatureList::IsEnabled(switches::kSyncUSSDeviceInfo)) { | 59 if (FeatureList::IsEnabled(switches::kSyncUSSDeviceInfo)) { |
| 54 set.Put(syncer::DEVICE_INFO); | 60 set.Put(syncer::DEVICE_INFO); |
| 55 } | 61 } |
| 62 // PRINTERS was the first USS type, and should precede all other USS types. |
| 63 // All new types should be USS. This logic is fragile to reordering ModelType. |
| 64 for (int typeInt = syncer::PRINTERS; typeInt < syncer::FIRST_PROXY_TYPE; |
| 65 typeInt++) { |
| 66 set.Put(static_cast<ModelType>(typeInt)); |
| 67 } |
| 56 return set; | 68 return set; |
| 57 } | 69 } |
| 58 | 70 |
| 71 // Some types show up in multiple groups. This means that there are at least two |
| 72 // user selectable groups that will cause these types to become enabled. This |
| 73 // affects our tests because we cannot assume that before enabling a multi type |
| 74 // it will be disabled, because the other selectable type(s) could already be |
| 75 // enabling it. And vice versa for disabling. |
| 76 ModelTypeSet MultiGroupTypes(const SyncPrefs& sync_prefs, |
| 77 const ModelTypeSet& registered_types) { |
| 78 const ModelTypeSet selectable_types = UserSelectableTypes(); |
| 79 ModelTypeSet seen; |
| 80 ModelTypeSet multi; |
| 81 for (ModelTypeSet::Iterator si = selectable_types.First(); si.Good(); |
| 82 si.Inc()) { |
| 83 const ModelTypeSet grouped_types = |
| 84 sync_prefs.ResolvePrefGroups(registered_types, ModelTypeSet(si.Get())); |
| 85 for (ModelTypeSet::Iterator gi = grouped_types.First(); gi.Good(); |
| 86 gi.Inc()) { |
| 87 if (seen.Has(gi.Get())) { |
| 88 multi.Put(gi.Get()); |
| 89 } else { |
| 90 seen.Put(gi.Get()); |
| 91 } |
| 92 } |
| 93 } |
| 94 return multi; |
| 95 } |
| 96 |
| 97 // This test enables and disables types and verifies the type is sufficiently |
| 98 // affected by checking for existence of a root node. |
| 99 class EnableDisableSingleClientTest : public SyncTest { |
| 100 public: |
| 101 EnableDisableSingleClientTest() : SyncTest(SINGLE_CLIENT) {} |
| 102 ~EnableDisableSingleClientTest() override {} |
| 103 |
| 104 // Don't use self-notifications as they can trigger additional sync cycles. |
| 105 bool TestUsesSelfNotifications() override { return false; } |
| 106 |
| 107 protected: |
| 108 void SetupTest(bool all_types_enabled) { |
| 109 ASSERT_TRUE(SetupClients()); |
| 110 sync_prefs_ = base::MakeUnique<SyncPrefs>(GetProfile(0)->GetPrefs()); |
| 111 if (all_types_enabled) { |
| 112 ASSERT_TRUE(GetClient(0)->SetupSync()); |
| 113 } else { |
| 114 ASSERT_TRUE(GetClient(0)->SetupSync(ModelTypeSet())); |
| 115 } |
| 116 user_share_ = GetSyncService(0)->GetUserShare(); |
| 117 data_type_status_table_ = GetSyncService(0)->data_type_status_table(); |
| 118 |
| 119 registered_types_ = GetSyncService(0)->GetRegisteredDataTypes(); |
| 120 selectable_types_ = UserSelectableTypes(); |
| 121 multi_grouped_types_ = MultiGroupTypes(*sync_prefs_, registered_types_); |
| 122 registered_directory_types_ = Difference( |
| 123 Difference(registered_types_, UnifiedSyncServiceTypes()), ProxyTypes()); |
| 124 registered_selectable_types_ = |
| 125 Intersection(registered_types_, UserSelectableTypes()); |
| 126 } |
| 127 |
| 128 ModelTypeSet ResolveGroup(ModelType type) { |
| 129 return Difference(Difference(sync_prefs_->ResolvePrefGroups( |
| 130 registered_types_, ModelTypeSet(type)), |
| 131 ProxyTypes()), |
| 132 UnifiedSyncServiceTypes()); |
| 133 } |
| 134 |
| 135 ModelTypeSet WithoutMultiTypes(const ModelTypeSet& input) { |
| 136 return Difference(input, multi_grouped_types_); |
| 137 } |
| 138 |
| 139 void TearDownOnMainThread() override { |
| 140 // Has to be done before user prefs are destroyed. |
| 141 sync_prefs_.reset(); |
| 142 SyncTest::TearDownOnMainThread(); |
| 143 } |
| 144 |
| 145 std::unique_ptr<SyncPrefs> sync_prefs_; |
| 146 UserShare* user_share_; |
| 147 syncer::DataTypeStatusTable data_type_status_table_; |
| 148 ModelTypeSet registered_types_; |
| 149 ModelTypeSet selectable_types_; |
| 150 ModelTypeSet multi_grouped_types_; |
| 151 ModelTypeSet registered_directory_types_; |
| 152 ModelTypeSet registered_selectable_types_; |
| 153 |
| 154 private: |
| 155 DISALLOW_COPY_AND_ASSIGN(EnableDisableSingleClientTest); |
| 156 }; |
| 157 |
| 59 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, EnableOneAtATime) { | 158 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, EnableOneAtATime) { |
| 60 ASSERT_TRUE(SetupClients()); | 159 // Setup sync with no enabled types. |
| 160 SetupTest(false); |
| 61 | 161 |
| 62 // Setup sync with no enabled types. | 162 for (ModelTypeSet::Iterator si = selectable_types_.First(); si.Good(); |
| 63 ASSERT_TRUE(GetClient(0)->SetupSync(ModelTypeSet())); | 163 si.Inc()) { |
| 64 | 164 const ModelTypeSet grouped_types = ResolveGroup(si.Get()); |
| 65 syncer::UserShare* user_share = GetSyncService(0)->GetUserShare(); | 165 const ModelTypeSet single_grouped_types = WithoutMultiTypes(grouped_types); |
| 66 const syncer::DataTypeStatusTable& data_type_status_table = | 166 for (ModelTypeSet::Iterator sgi = single_grouped_types.First(); sgi.Good(); |
| 67 GetSyncService(0)->data_type_status_table(); | 167 sgi.Inc()) { |
| 68 | 168 VerifyExistence(user_share_, false, sgi.Get(), si.Get()); |
| 69 const ModelTypeSet registered_types = | |
| 70 GetSyncService(0)->GetRegisteredDataTypes(); | |
| 71 const ModelTypeSet registered_directory_types = | |
| 72 Difference(registered_types, UnifiedSyncServiceTypes()); | |
| 73 const ModelTypeSet registered_directory_user_types = | |
| 74 Intersection(registered_types, syncer::UserSelectableTypes()); | |
| 75 for (ModelTypeSet::Iterator it = registered_directory_user_types.First(); | |
| 76 it.Good(); it.Inc()) { | |
| 77 ASSERT_TRUE(GetClient(0)->EnableSyncForDatatype(it.Get())); | |
| 78 | |
| 79 // AUTOFILL_PROFILE is lumped together with AUTOFILL. | |
| 80 // SESSIONS is lumped together with PROXY_TABS and | |
| 81 // HISTORY_DELETE_DIRECTIVES. | |
| 82 // Favicons are lumped together with PROXY_TABS and | |
| 83 // HISTORY_DELETE_DIRECTIVES. | |
| 84 if (it.Get() == syncer::AUTOFILL_PROFILE || it.Get() == syncer::SESSIONS) { | |
| 85 continue; | |
| 86 } | 169 } |
| 87 | 170 |
| 88 if (!syncer::ProxyTypes().Has(it.Get())) { | 171 EXPECT_TRUE(GetClient(0)->EnableSyncForDatatype(si.Get())); |
| 89 ASSERT_TRUE(DoesTopLevelNodeExist(user_share, it.Get()) || | |
| 90 IsUnready(data_type_status_table, it.Get())) | |
| 91 << syncer::ModelTypeToString(it.Get()); | |
| 92 } | |
| 93 | 172 |
| 94 // AUTOFILL_PROFILE is lumped together with AUTOFILL. | 173 for (ModelTypeSet::Iterator gi = grouped_types.First(); gi.Good(); |
| 95 if (it.Get() == syncer::AUTOFILL) { | 174 gi.Inc()) { |
| 96 ASSERT_TRUE(DoesTopLevelNodeExist(user_share, | 175 VerifyExistence(user_share_, true, gi.Get(), si.Get()); |
| 97 syncer::AUTOFILL_PROFILE)); | |
| 98 } else if (it.Get() == syncer::HISTORY_DELETE_DIRECTIVES || | |
| 99 it.Get() == syncer::PROXY_TABS) { | |
| 100 ASSERT_TRUE(DoesTopLevelNodeExist(user_share, | |
| 101 syncer::SESSIONS)); | |
| 102 } | 176 } |
| 103 } | 177 } |
| 104 } | 178 } |
| 105 | 179 |
| 106 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, DisableOneAtATime) { | 180 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, DisableOneAtATime) { |
| 107 ASSERT_TRUE(SetupClients()); | |
| 108 | |
| 109 // Setup sync with no disabled types. | 181 // Setup sync with no disabled types. |
| 110 ASSERT_TRUE(GetClient(0)->SetupSync()); | 182 SetupTest(true); |
| 111 | |
| 112 const ModelTypeSet registered_types = | |
| 113 GetSyncService(0)->GetRegisteredDataTypes(); | |
| 114 const ModelTypeSet registered_directory_types = | |
| 115 Difference(registered_types, UnifiedSyncServiceTypes()); | |
| 116 | |
| 117 syncer::UserShare* user_share = GetSyncService(0)->GetUserShare(); | |
| 118 | |
| 119 const syncer::DataTypeStatusTable& data_type_status_table = | |
| 120 GetSyncService(0)->data_type_status_table(); | |
| 121 | 183 |
| 122 // Make sure all top-level nodes exist first. | 184 // Make sure all top-level nodes exist first. |
| 123 for (ModelTypeSet::Iterator it = registered_directory_types.First(); | 185 for (ModelTypeSet::Iterator rdi = registered_directory_types_.First(); |
| 124 it.Good(); it.Inc()) { | 186 rdi.Good(); rdi.Inc()) { |
| 125 if (!syncer::ProxyTypes().Has(it.Get())) { | 187 EXPECT_TRUE(DoesTopLevelNodeExist(user_share_, rdi.Get()) || |
| 126 ASSERT_TRUE(DoesTopLevelNodeExist(user_share, it.Get()) || | 188 IsUnready(data_type_status_table_, rdi.Get())) |
| 127 IsUnready(data_type_status_table, it.Get())); | 189 << ModelTypeToString(rdi.Get()); |
| 190 } |
| 191 |
| 192 for (ModelTypeSet::Iterator si = selectable_types_.First(); si.Good(); |
| 193 si.Inc()) { |
| 194 const ModelTypeSet grouped_types = ResolveGroup(si.Get()); |
| 195 for (ModelTypeSet::Iterator gi = grouped_types.First(); gi.Good(); |
| 196 gi.Inc()) { |
| 197 VerifyExistence(user_share_, true, gi.Get(), si.Get()); |
| 198 } |
| 199 |
| 200 EXPECT_TRUE(GetClient(0)->DisableSyncForDatatype(si.Get())); |
| 201 |
| 202 const ModelTypeSet single_grouped_types = WithoutMultiTypes(grouped_types); |
| 203 for (ModelTypeSet::Iterator sgi = single_grouped_types.First(); sgi.Good(); |
| 204 sgi.Inc()) { |
| 205 VerifyExistence(user_share_, false, sgi.Get(), si.Get()); |
| 128 } | 206 } |
| 129 } | 207 } |
| 130 | 208 |
| 131 for (ModelTypeSet::Iterator it = registered_directory_types.First(); | 209 // Lastly make sure that all the multi grouped times are all gone, since we |
| 132 it.Good(); it.Inc()) { | 210 // did not check these after disabling inside the above loop. |
| 133 // SUPERVISED_USERS and SUPERVISED_USER_SHARED_SETTINGS are always synced. | 211 for (ModelTypeSet::Iterator mgi = multi_grouped_types_.First(); mgi.Good(); |
| 134 if (it.Get() == syncer::SUPERVISED_USERS || | 212 mgi.Inc()) { |
| 135 it.Get() == syncer::SUPERVISED_USER_SHARED_SETTINGS || | 213 VerifyExistence(user_share_, false, mgi.Get()); |
| 136 it.Get() == syncer::SYNCED_NOTIFICATIONS || | |
| 137 it.Get() == syncer::SYNCED_NOTIFICATION_APP_INFO) | |
| 138 continue; | |
| 139 | |
| 140 // Device info cannot be disabled. | |
| 141 if (it.Get() == syncer::DEVICE_INFO) | |
| 142 continue; | |
| 143 | |
| 144 ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(it.Get())); | |
| 145 | |
| 146 // AUTOFILL_PROFILE is lumped together with AUTOFILL. | |
| 147 // SESSIONS is lumped together with PROXY_TABS and TYPED_URLS. | |
| 148 // HISTORY_DELETE_DIRECTIVES is lumped together with TYPED_URLS. | |
| 149 // PRIORITY_PREFERENCES is lumped together with PREFERENCES. | |
| 150 // Favicons are lumped together with PROXY_TABS and | |
| 151 // HISTORY_DELETE_DIRECTIVES. | |
| 152 if (it.Get() == syncer::AUTOFILL_PROFILE || | |
| 153 it.Get() == syncer::SESSIONS || | |
| 154 it.Get() == syncer::HISTORY_DELETE_DIRECTIVES || | |
| 155 it.Get() == syncer::PRIORITY_PREFERENCES || | |
| 156 it.Get() == syncer::FAVICON_IMAGES || | |
| 157 it.Get() == syncer::FAVICON_TRACKING) { | |
| 158 continue; | |
| 159 } | |
| 160 | |
| 161 syncer::UserShare* user_share = | |
| 162 GetSyncService(0)->GetUserShare(); | |
| 163 | |
| 164 ASSERT_FALSE(DoesTopLevelNodeExist(user_share, it.Get())) | |
| 165 << syncer::ModelTypeToString(it.Get()); | |
| 166 | |
| 167 if (it.Get() == syncer::AUTOFILL) { | |
| 168 // AUTOFILL_PROFILE is lumped together with AUTOFILL. | |
| 169 ASSERT_FALSE(DoesTopLevelNodeExist(user_share, syncer::AUTOFILL_PROFILE)); | |
| 170 } else if (it.Get() == syncer::TYPED_URLS) { | |
| 171 ASSERT_FALSE(DoesTopLevelNodeExist(user_share, | |
| 172 syncer::HISTORY_DELETE_DIRECTIVES)); | |
| 173 // SESSIONS should be enabled only if PROXY_TABS is. | |
| 174 ASSERT_EQ(GetClient(0)->IsTypePreferred(syncer::PROXY_TABS), | |
| 175 DoesTopLevelNodeExist(user_share, syncer::SESSIONS)); | |
| 176 } else if (it.Get() == syncer::PROXY_TABS) { | |
| 177 // SESSIONS should be enabled only if TYPED_URLS is. | |
| 178 ASSERT_EQ(GetClient(0)->IsTypePreferred(syncer::TYPED_URLS), | |
| 179 DoesTopLevelNodeExist(user_share, syncer::SESSIONS)); | |
| 180 } else if (it.Get() == syncer::PREFERENCES) { | |
| 181 ASSERT_FALSE(DoesTopLevelNodeExist(user_share, | |
| 182 syncer::PRIORITY_PREFERENCES)); | |
| 183 } | |
| 184 } | 214 } |
| 185 } | 215 } |
| 186 | 216 |
| 187 } // namespace | 217 } // namespace |
| OLD | NEW |