| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 <stddef.h> | 5 #include <stddef.h> |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 #include "extensions/browser/extension_registry.h" | 36 #include "extensions/browser/extension_registry.h" |
| 37 #include "extensions/browser/extension_system.h" | 37 #include "extensions/browser/extension_system.h" |
| 38 #include "extensions/browser/management_policy.h" | 38 #include "extensions/browser/management_policy.h" |
| 39 #include "extensions/browser/test_management_policy.h" | 39 #include "extensions/browser/test_management_policy.h" |
| 40 #include "extensions/common/constants.h" | 40 #include "extensions/common/constants.h" |
| 41 #include "extensions/common/extension_builder.h" | 41 #include "extensions/common/extension_builder.h" |
| 42 #include "extensions/common/manifest_url_handlers.h" | 42 #include "extensions/common/manifest_url_handlers.h" |
| 43 #include "extensions/common/permissions/permission_set.h" | 43 #include "extensions/common/permissions/permission_set.h" |
| 44 #include "extensions/common/value_builder.h" | 44 #include "extensions/common/value_builder.h" |
| 45 #include "sync/api/fake_sync_change_processor.h" | 45 #include "sync/api/fake_sync_change_processor.h" |
| 46 #include "sync/api/sync_change_processor_wrapper_for_test.h" |
| 46 #include "sync/api/sync_data.h" | 47 #include "sync/api/sync_data.h" |
| 47 #include "sync/api/sync_error_factory_mock.h" | 48 #include "sync/api/sync_error_factory_mock.h" |
| 48 #include "testing/gtest/include/gtest/gtest.h" | 49 #include "testing/gtest/include/gtest/gtest.h" |
| 49 | 50 |
| 50 #if defined(ENABLE_SUPERVISED_USERS) | 51 #if defined(ENABLE_SUPERVISED_USERS) |
| 51 #include "chrome/browser/supervised_user/permission_request_creator.h" | 52 #include "chrome/browser/supervised_user/permission_request_creator.h" |
| 52 #include "chrome/browser/supervised_user/supervised_user_constants.h" | 53 #include "chrome/browser/supervised_user/supervised_user_constants.h" |
| 53 #include "chrome/browser/supervised_user/supervised_user_service.h" | 54 #include "chrome/browser/supervised_user/supervised_user_service.h" |
| 54 #include "chrome/browser/supervised_user/supervised_user_service_factory.h" | 55 #include "chrome/browser/supervised_user/supervised_user_service_factory.h" |
| 55 #endif | 56 #endif |
| (...skipping 17 matching lines...) Expand all Loading... |
| 73 const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; | 74 const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; |
| 74 | 75 |
| 75 SyncChangeList MakeSyncChangeList(const std::string& id, | 76 SyncChangeList MakeSyncChangeList(const std::string& id, |
| 76 const sync_pb::EntitySpecifics& specifics, | 77 const sync_pb::EntitySpecifics& specifics, |
| 77 SyncChange::SyncChangeType change_type) { | 78 SyncChange::SyncChangeType change_type) { |
| 78 syncer::SyncData sync_data = | 79 syncer::SyncData sync_data = |
| 79 syncer::SyncData::CreateLocalData(id, "Name", specifics); | 80 syncer::SyncData::CreateLocalData(id, "Name", specifics); |
| 80 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data)); | 81 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data)); |
| 81 } | 82 } |
| 82 | 83 |
| 84 // This is a FakeSyncChangeProcessor specialization that maintains a store of |
| 85 // SyncData items in the superclass' data_ member variable, treating it like a |
| 86 // map keyed by the extension id from the SyncData. Each instance of this class |
| 87 // should only be used for one model type (which should be either extensions or |
| 88 // apps) to match how the real sync system handles things. |
| 89 class StatefulChangeProcessor : public syncer::FakeSyncChangeProcessor { |
| 90 public: |
| 91 explicit StatefulChangeProcessor(syncer::ModelType expected_type) |
| 92 : expected_type_(expected_type) { |
| 93 EXPECT_TRUE(expected_type == syncer::ModelType::EXTENSIONS || |
| 94 expected_type == syncer::ModelType::APPS); |
| 95 } |
| 96 |
| 97 ~StatefulChangeProcessor() override {} |
| 98 |
| 99 // We let our parent class, FakeSyncChangeProcessor, handle saving the |
| 100 // changes for us, but in addition we "apply" these changes by treating |
| 101 // the FakeSyncChangeProcessor's SyncDataList as a map keyed by extension |
| 102 // id. |
| 103 syncer::SyncError ProcessSyncChanges( |
| 104 const tracked_objects::Location& from_here, |
| 105 const syncer::SyncChangeList& change_list) override { |
| 106 syncer::FakeSyncChangeProcessor::ProcessSyncChanges(from_here, change_list); |
| 107 for (const auto& change : change_list) { |
| 108 syncer::SyncData sync_data = change.sync_data(); |
| 109 EXPECT_EQ(expected_type_, sync_data.GetDataType()); |
| 110 |
| 111 scoped_ptr<ExtensionSyncData> modified = |
| 112 ExtensionSyncData::CreateFromSyncData(sync_data); |
| 113 |
| 114 // Start by removing any existing entry for this extension id. |
| 115 syncer::SyncDataList& data_list = data(); |
| 116 for (auto iter = data_list.begin(); iter != data_list.end(); ++iter) { |
| 117 scoped_ptr<ExtensionSyncData> existing = |
| 118 ExtensionSyncData::CreateFromSyncData(*iter); |
| 119 if (existing->id() == modified->id()) { |
| 120 data_list.erase(iter); |
| 121 break; |
| 122 } |
| 123 } |
| 124 |
| 125 // Now add in the new data for this id, if appropriate. |
| 126 if (change.change_type() == SyncChange::ACTION_ADD || |
| 127 change.change_type() == SyncChange::ACTION_UPDATE) { |
| 128 data_list.push_back(sync_data); |
| 129 } else if (change.change_type() != SyncChange::ACTION_DELETE) { |
| 130 ADD_FAILURE() << "Unexpected change type " << change.change_type(); |
| 131 } |
| 132 } |
| 133 return syncer::SyncError(); |
| 134 } |
| 135 |
| 136 // We override this to help catch the error of trying to use a single |
| 137 // StatefulChangeProcessor to process changes for both extensions and apps |
| 138 // sync data. |
| 139 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override { |
| 140 EXPECT_EQ(expected_type_, type); |
| 141 return FakeSyncChangeProcessor::GetAllSyncData(type); |
| 142 } |
| 143 |
| 144 // This is a helper to vend a wrapped version of this object suitable for |
| 145 // passing in to MergeDataAndStartSyncing, which takes a |
| 146 // scoped_ptr<SyncChangeProcessor>, since in tests we typically don't want to |
| 147 // give up ownership of a local change processor. |
| 148 scoped_ptr<syncer::SyncChangeProcessor> GetWrapped() { |
| 149 return make_scoped_ptr(new syncer::SyncChangeProcessorWrapperForTest(this)); |
| 150 } |
| 151 |
| 152 protected: |
| 153 // The expected ModelType of changes that this processor will see. |
| 154 syncer::ModelType expected_type_; |
| 155 |
| 156 DISALLOW_COPY_AND_ASSIGN(StatefulChangeProcessor); |
| 157 }; |
| 158 |
| 83 } // namespace | 159 } // namespace |
| 84 | 160 |
| 85 class ExtensionServiceSyncTest | 161 class ExtensionServiceSyncTest |
| 86 : public extensions::ExtensionServiceTestWithInstall { | 162 : public extensions::ExtensionServiceTestWithInstall { |
| 87 public: | 163 public: |
| 88 void MockSyncStartFlare(bool* was_called, | 164 void MockSyncStartFlare(bool* was_called, |
| 89 syncer::ModelType* model_type_passed_in, | 165 syncer::ModelType* model_type_passed_in, |
| 90 syncer::ModelType model_type) { | 166 syncer::ModelType model_type) { |
| 91 *was_called = true; | 167 *was_called = true; |
| 92 *model_type_passed_in = model_type; | 168 *model_type_passed_in = model_type; |
| 93 } | 169 } |
| 94 | 170 |
| 171 // Helper to call MergeDataAndStartSyncing with no server data and dummy |
| 172 // change processor / error factory. |
| 173 void StartSyncing(syncer::ModelType type) { |
| 174 ASSERT_TRUE(type == syncer::EXTENSIONS || type == syncer::APPS); |
| 175 extension_sync_service()->MergeDataAndStartSyncing( |
| 176 type, syncer::SyncDataList(), |
| 177 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()), |
| 178 make_scoped_ptr(new syncer::SyncErrorFactoryMock())); |
| 179 } |
| 180 |
| 95 protected: | 181 protected: |
| 96 // Paths to some of the fake extensions. | 182 // Paths to some of the fake extensions. |
| 97 base::FilePath good0_path() { | 183 base::FilePath good0_path() { |
| 98 return data_dir() | 184 return data_dir() |
| 99 .AppendASCII("good") | 185 .AppendASCII("good") |
| 100 .AppendASCII("Extensions") | 186 .AppendASCII("Extensions") |
| 101 .AppendASCII(good0) | 187 .AppendASCII(good0) |
| 102 .AppendASCII("1.0.0.0"); | 188 .AppendASCII("1.0.0.0"); |
| 103 } | 189 } |
| 104 | 190 |
| (...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 InitializeEmptyExtensionService(); | 687 InitializeEmptyExtensionService(); |
| 602 InstallCRXWithLocation( | 688 InstallCRXWithLocation( |
| 603 data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF, INSTALL_NEW); | 689 data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF, INSTALL_NEW); |
| 604 const Extension* extension = service()->GetInstalledExtension(good_crx); | 690 const Extension* extension = service()->GetInstalledExtension(good_crx); |
| 605 ASSERT_TRUE(extension); | 691 ASSERT_TRUE(extension); |
| 606 | 692 |
| 607 extension_sync_service()->MergeDataAndStartSyncing( | 693 extension_sync_service()->MergeDataAndStartSyncing( |
| 608 syncer::EXTENSIONS, syncer::SyncDataList(), | 694 syncer::EXTENSIONS, syncer::SyncDataList(), |
| 609 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()), | 695 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()), |
| 610 make_scoped_ptr(new syncer::SyncErrorFactoryMock())); | 696 make_scoped_ptr(new syncer::SyncErrorFactoryMock())); |
| 697 StartSyncing(syncer::APPS); |
| 611 | 698 |
| 612 UninstallExtension(good_crx, false); | 699 UninstallExtension(good_crx, false); |
| 613 EXPECT_TRUE( | 700 EXPECT_TRUE( |
| 614 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx)); | 701 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx)); |
| 615 | 702 |
| 616 sync_pb::EntitySpecifics specifics; | 703 sync_pb::EntitySpecifics specifics; |
| 617 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app(); | 704 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app(); |
| 618 sync_pb::ExtensionSpecifics* extension_specifics = | 705 sync_pb::ExtensionSpecifics* extension_specifics = |
| 619 app_specifics->mutable_extension(); | 706 app_specifics->mutable_extension(); |
| 620 extension_specifics->set_id(good_crx); | 707 extension_specifics->set_id(good_crx); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | 872 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); |
| 786 EXPECT_FALSE(service()->GetExtensionById(good_crx, true)); | 873 EXPECT_FALSE(service()->GetExtensionById(good_crx, true)); |
| 787 | 874 |
| 788 // Should again do nothing. | 875 // Should again do nothing. |
| 789 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | 876 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); |
| 790 EXPECT_FALSE(service()->GetExtensionById(good_crx, true)); | 877 EXPECT_FALSE(service()->GetExtensionById(good_crx, true)); |
| 791 } | 878 } |
| 792 | 879 |
| 793 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) { | 880 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) { |
| 794 InitializeEmptyExtensionService(); | 881 InitializeEmptyExtensionService(); |
| 882 StartSyncing(syncer::EXTENSIONS); |
| 883 StartSyncing(syncer::APPS); |
| 795 | 884 |
| 796 // Install the extension. | 885 // Install the extension. |
| 797 base::FilePath extension_path = data_dir().AppendASCII("good.crx"); | 886 base::FilePath extension_path = data_dir().AppendASCII("good.crx"); |
| 798 InstallCRX(extension_path, INSTALL_NEW); | 887 InstallCRX(extension_path, INSTALL_NEW); |
| 799 EXPECT_TRUE(service()->GetExtensionById(good_crx, true)); | 888 EXPECT_TRUE(service()->GetExtensionById(good_crx, true)); |
| 800 | 889 |
| 801 sync_pb::EntitySpecifics specifics; | 890 sync_pb::EntitySpecifics specifics; |
| 802 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app(); | 891 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app(); |
| 803 sync_pb::ExtensionSpecifics* extension_specifics = | 892 sync_pb::ExtensionSpecifics* extension_specifics = |
| 804 app_specifics->mutable_extension(); | 893 app_specifics->mutable_extension(); |
| (...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1479 params["legacy_supervised_user"] = enabled ? "true" : "false"; | 1568 params["legacy_supervised_user"] = enabled ? "true" : "false"; |
| 1480 params["child_account"] = enabled ? "true" : "false"; | 1569 params["child_account"] = enabled ? "true" : "false"; |
| 1481 variations::AssociateVariationParams( | 1570 variations::AssociateVariationParams( |
| 1482 "SupervisedUserExtensionPermissionIncrease", "group", params); | 1571 "SupervisedUserExtensionPermissionIncrease", "group", params); |
| 1483 } | 1572 } |
| 1484 | 1573 |
| 1485 void InitServices(bool profile_is_supervised) { | 1574 void InitServices(bool profile_is_supervised) { |
| 1486 ExtensionServiceInitParams params = CreateDefaultInitParams(); | 1575 ExtensionServiceInitParams params = CreateDefaultInitParams(); |
| 1487 params.profile_is_supervised = profile_is_supervised; | 1576 params.profile_is_supervised = profile_is_supervised; |
| 1488 InitializeExtensionService(params); | 1577 InitializeExtensionService(params); |
| 1578 StartSyncing(syncer::EXTENSIONS); |
| 1489 | 1579 |
| 1490 supervised_user_service()->SetDelegate(this); | 1580 supervised_user_service()->SetDelegate(this); |
| 1491 supervised_user_service()->Init(); | 1581 supervised_user_service()->Init(); |
| 1492 } | 1582 } |
| 1493 | 1583 |
| 1494 std::string InstallPermissionsTestExtension() { | 1584 std::string InstallPermissionsTestExtension() { |
| 1495 const std::string version("1"); | 1585 const std::string version("1"); |
| 1496 | 1586 |
| 1497 const Extension* extension = | 1587 const Extension* extension = |
| 1498 PackAndInstallCRX(dir_path(version), pem_path(), INSTALL_NEW, | 1588 PackAndInstallCRX(dir_path(version), pem_path(), INSTALL_NEW, |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1826 // blocked by policy, so it should still be there. | 1916 // blocked by policy, so it should still be there. |
| 1827 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0])); | 1917 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0])); |
| 1828 | 1918 |
| 1829 // But installed_by_custodian should result in bypassing the policy check. | 1919 // But installed_by_custodian should result in bypassing the policy check. |
| 1830 EXPECT_FALSE( | 1920 EXPECT_FALSE( |
| 1831 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1])); | 1921 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1])); |
| 1832 } | 1922 } |
| 1833 | 1923 |
| 1834 TEST_F(ExtensionServiceSyncTest, SyncExtensionHasAllhostsWithheld) { | 1924 TEST_F(ExtensionServiceSyncTest, SyncExtensionHasAllhostsWithheld) { |
| 1835 InitializeEmptyExtensionService(); | 1925 InitializeEmptyExtensionService(); |
| 1926 StartSyncing(syncer::EXTENSIONS); |
| 1836 | 1927 |
| 1837 // Create an extension that needs all-hosts. | 1928 // Create an extension that needs all-hosts. |
| 1838 const std::string kName("extension"); | 1929 const std::string kName("extension"); |
| 1839 scoped_refptr<const Extension> extension = | 1930 scoped_refptr<const Extension> extension = |
| 1840 extensions::ExtensionBuilder() | 1931 extensions::ExtensionBuilder() |
| 1841 .SetLocation(Manifest::INTERNAL) | 1932 .SetLocation(Manifest::INTERNAL) |
| 1842 .SetManifest( | 1933 .SetManifest( |
| 1843 extensions::DictionaryBuilder() | 1934 extensions::DictionaryBuilder() |
| 1844 .Set("name", kName) | 1935 .Set("name", kName) |
| 1845 .Set("description", "foo") | 1936 .Set("description", "foo") |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1872 | 1963 |
| 1873 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); | 1964 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list); |
| 1874 | 1965 |
| 1875 EXPECT_TRUE(registry()->enabled_extensions().GetByID(id)); | 1966 EXPECT_TRUE(registry()->enabled_extensions().GetByID(id)); |
| 1876 EXPECT_FALSE(extensions::util::AllowedScriptingOnAllUrls(id, profile())); | 1967 EXPECT_FALSE(extensions::util::AllowedScriptingOnAllUrls(id, profile())); |
| 1877 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls(id, profile())); | 1968 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls(id, profile())); |
| 1878 EXPECT_FALSE(extensions::util::AllowedScriptingOnAllUrls(id, profile())); | 1969 EXPECT_FALSE(extensions::util::AllowedScriptingOnAllUrls(id, profile())); |
| 1879 } | 1970 } |
| 1880 | 1971 |
| 1881 #endif // defined(ENABLE_SUPERVISED_USERS) | 1972 #endif // defined(ENABLE_SUPERVISED_USERS) |
| 1973 |
| 1974 // Tests sync behavior in the case of an item that starts out as an app and |
| 1975 // gets updated to become an extension. |
| 1976 TEST_F(ExtensionServiceSyncTest, AppToExtension) { |
| 1977 InitializeEmptyExtensionService(); |
| 1978 service()->Init(); |
| 1979 ASSERT_TRUE(service()->is_ready()); |
| 1980 |
| 1981 // Install v1, which is an app. |
| 1982 const Extension* v1 = |
| 1983 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"), |
| 1984 INSTALL_NEW); |
| 1985 EXPECT_TRUE(v1->is_app()); |
| 1986 EXPECT_FALSE(v1->is_extension()); |
| 1987 std::string id = v1->id(); |
| 1988 |
| 1989 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS); |
| 1990 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS); |
| 1991 extension_sync_service()->MergeDataAndStartSyncing( |
| 1992 syncer::EXTENSIONS, syncer::SyncDataList(), |
| 1993 extensions_processor.GetWrapped(), |
| 1994 make_scoped_ptr(new syncer::SyncErrorFactoryMock())); |
| 1995 extension_sync_service()->MergeDataAndStartSyncing( |
| 1996 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(), |
| 1997 make_scoped_ptr(new syncer::SyncErrorFactoryMock())); |
| 1998 |
| 1999 // Check the app/extension change processors to be sure the right data was |
| 2000 // added. |
| 2001 EXPECT_TRUE(extensions_processor.changes().empty()); |
| 2002 EXPECT_TRUE(extensions_processor.data().empty()); |
| 2003 EXPECT_EQ(1u, apps_processor.data().size()); |
| 2004 ASSERT_EQ(1u, apps_processor.changes().size()); |
| 2005 const SyncChange& app_change = apps_processor.changes()[0]; |
| 2006 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type()); |
| 2007 scoped_ptr<ExtensionSyncData> app_data = |
| 2008 ExtensionSyncData::CreateFromSyncData(app_change.sync_data()); |
| 2009 EXPECT_TRUE(app_data->is_app()); |
| 2010 EXPECT_EQ(id, app_data->id()); |
| 2011 EXPECT_EQ(*v1->version(), app_data->version()); |
| 2012 |
| 2013 // Update the app to v2, which is an extension. |
| 2014 const Extension* v2 = |
| 2015 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"), |
| 2016 INSTALL_UPDATED); |
| 2017 EXPECT_FALSE(v2->is_app()); |
| 2018 EXPECT_TRUE(v2->is_extension()); |
| 2019 EXPECT_EQ(id, v2->id()); |
| 2020 |
| 2021 // Make sure we saw an extension item added. |
| 2022 ASSERT_EQ(1u, extensions_processor.changes().size()); |
| 2023 const SyncChange& extension_change = extensions_processor.changes()[0]; |
| 2024 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type()); |
| 2025 scoped_ptr<ExtensionSyncData> extension_data = |
| 2026 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data()); |
| 2027 EXPECT_FALSE(extension_data->is_app()); |
| 2028 EXPECT_EQ(id, extension_data->id()); |
| 2029 EXPECT_EQ(*v2->version(), extension_data->version()); |
| 2030 |
| 2031 // Get the current data from the change processors to use as the input to |
| 2032 // the following call to MergeDataAndStartSyncing. This simulates what should |
| 2033 // happen with sync. |
| 2034 syncer::SyncDataList extensions_data = |
| 2035 extensions_processor.GetAllSyncData(syncer::EXTENSIONS); |
| 2036 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS); |
| 2037 |
| 2038 // Stop syncing, then start again. |
| 2039 extension_sync_service()->StopSyncing(syncer::EXTENSIONS); |
| 2040 extension_sync_service()->StopSyncing(syncer::APPS); |
| 2041 extension_sync_service()->MergeDataAndStartSyncing( |
| 2042 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(), |
| 2043 make_scoped_ptr(new syncer::SyncErrorFactoryMock())); |
| 2044 extension_sync_service()->MergeDataAndStartSyncing( |
| 2045 syncer::APPS, apps_data, apps_processor.GetWrapped(), |
| 2046 make_scoped_ptr(new syncer::SyncErrorFactoryMock())); |
| 2047 |
| 2048 // Make sure we saw an app item deleted. |
| 2049 bool found_delete = false; |
| 2050 for (const auto& change : apps_processor.changes()) { |
| 2051 if (change.change_type() == SyncChange::ACTION_DELETE) { |
| 2052 scoped_ptr<ExtensionSyncData> data = |
| 2053 ExtensionSyncData::CreateFromSyncChange(change); |
| 2054 if (data->id() == id) { |
| 2055 found_delete = true; |
| 2056 break; |
| 2057 } |
| 2058 } |
| 2059 } |
| 2060 EXPECT_TRUE(found_delete); |
| 2061 |
| 2062 // Make sure there is one extension, and there are no more apps. |
| 2063 EXPECT_EQ(1u, extensions_processor.data().size()); |
| 2064 EXPECT_TRUE(apps_processor.data().empty()); |
| 2065 } |
| OLD | NEW |