Index: chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc |
diff --git a/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc b/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc |
index a5cda2282a38829284cb1b8dedc8562d06fd7610..efb7788a2b6228dd156d84e53ea389dc8309509c 100644 |
--- a/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc |
+++ b/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc |
@@ -3,13 +3,18 @@ |
// found in the LICENSE file. |
#include "base/macros.h" |
+#include "chrome/browser/sync/test/integration/await_match_status_change_checker.h" |
#include "chrome/browser/sync/test/integration/extensions_helper.h" |
#include "chrome/browser/sync/test/integration/sync_integration_test_util.h" |
#include "chrome/browser/sync/test/integration/sync_test.h" |
#include "components/browser_sync/browser/profile_sync_service.h" |
+#include "sync/test/fake_server/tombstone_entity.h" |
using extensions_helper::AllProfilesHaveSameExtensionsAsVerifier; |
+using extensions_helper::DisableExtension; |
+using extensions_helper::GetInstalledExtensions; |
using extensions_helper::InstallExtension; |
+using extensions_helper::InstallExtensionForAllProfiles; |
using sync_integration_test_util::AwaitCommitActivityCompletion; |
class SingleClientExtensionsSyncTest : public SyncTest { |
@@ -56,3 +61,48 @@ IN_PROC_BROWSER_TEST_F(SingleClientExtensionsSyncTest, InstallSomeExtensions) { |
ASSERT_TRUE(AllProfilesHaveSameExtensionsAsVerifier()); |
} |
+ |
+// Helper function for waiting to see the extension count in a profile |
+// become a specific number. |
+static bool ExtensionCountCheck(Profile* profile, size_t expected_count) { |
+ return GetInstalledExtensions(profile).size() == expected_count; |
+} |
+ |
+// Tests the case of an uninstall from the server conflicting with a local |
+// modification, which we expect to be resolved in favor of the uninstall. |
+IN_PROC_BROWSER_TEST_F(SingleClientExtensionsSyncTest, UninstallWinsConflicts) { |
+ ASSERT_TRUE(SetupClients()); |
+ |
+ // Start with an extension installed, and setup sync. |
+ InstallExtensionForAllProfiles(0); |
+ ASSERT_TRUE(SetupSync()); |
+ EXPECT_TRUE(AllProfilesHaveSameExtensionsAsVerifier()); |
+ |
+ // Simulate a delete at the server. |
+ std::vector<sync_pb::SyncEntity> server_extensions = |
+ GetFakeServer()->GetSyncEntitiesByModelType(syncer::EXTENSIONS); |
+ ASSERT_EQ(1ul, server_extensions.size()); |
+ std::string entity_id = server_extensions[0].id_string(); |
+ scoped_ptr<fake_server::FakeServerEntity> tombstone( |
+ fake_server::TombstoneEntity::Create(entity_id)); |
+ GetFakeServer()->InjectEntity(std::move(tombstone)); |
+ |
+ // Modify the extension in the local profile to cause a conflict. |
+ DisableExtension(GetProfile(0), 0); |
+ EXPECT_EQ(1u, GetInstalledExtensions(GetProfile(0)).size()); |
+ |
+ // Trigger sync, and expect the extension to remain uninstalled at the server |
+ // and get uninstalled locally. |
+ const syncer::ModelTypeSet kExtensionsType(syncer::EXTENSIONS); |
+ TriggerSyncForModelTypes(0, kExtensionsType); |
+ server_extensions = |
+ GetFakeServer()->GetSyncEntitiesByModelType(syncer::EXTENSIONS); |
+ EXPECT_EQ(0ul, server_extensions.size()); |
+ |
+ AwaitMatchStatusChangeChecker checker( |
+ base::Bind(&ExtensionCountCheck, GetProfile(0), 0u), |
+ "Waiting for profile to have no extensions"); |
+ checker.Wait(); |
+ EXPECT_TRUE(!checker.TimedOut()); |
+ EXPECT_TRUE(GetInstalledExtensions(GetProfile(0)).empty()); |
+} |