| 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 |