Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(377)

Side by Side Diff: chrome/browser/extensions/extension_service_sync_unittest.cc

Issue 1778923003: Fix extensions sync in cases where items change type (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: review feedback Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_disabled_ui_browsertest.cc ('k') | chrome/browser/extensions/extension_sync_service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698