1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/bind.h"
6 #include "base/macros.h"
7 #include "chrome/browser/sync/test/integration/await_match_status_change_checker.h"
8 #include "chrome/browser/sync/test/integration/extensions_helper.h"
9 #include "chrome/browser/sync/test/integration/sync_test.h"
10 #include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
11 #include "components/sync/driver/profile_sync_service.h"
12 #include "components/sync/test/fake_server/fake_server.h"
13 #include "content/public/test/browser_test.h"
14
15 namespace {
16
17 using extensions_helper::AllProfilesHaveSameExtensionsAsVerifier;
18 using extensions_helper::DisableExtension;
19 using extensions_helper::GetInstalledExtensions;
20 using extensions_helper::InstallExtension;
21 using extensions_helper::InstallExtensionForAllProfiles;
22
23 class SingleClientExtensionsSyncTest : public SyncTest {
24 public:
SingleClientExtensionsSyncTest()25 SingleClientExtensionsSyncTest() : SyncTest(SINGLE_CLIENT) {}
26 ~SingleClientExtensionsSyncTest() override = default;
27
UseVerifier()28 bool UseVerifier() override {
29 // TODO(crbug.com/1137717): rewrite tests to not use verifier profile.
30 return true;
31 }
32 };
33
IN_PROC_BROWSER_TEST_F(SingleClientExtensionsSyncTest,StartWithNoExtensions)34 IN_PROC_BROWSER_TEST_F(SingleClientExtensionsSyncTest, StartWithNoExtensions) {
35 ASSERT_TRUE(SetupSync());
36 ASSERT_TRUE(AllProfilesHaveSameExtensionsAsVerifier());
37 }
38
IN_PROC_BROWSER_TEST_F(SingleClientExtensionsSyncTest,StartWithSomeExtensions)39 IN_PROC_BROWSER_TEST_F(SingleClientExtensionsSyncTest,
40 StartWithSomeExtensions) {
41 ASSERT_TRUE(SetupClients());
42
43 const int kNumExtensions = 5;
44 for (int i = 0; i < kNumExtensions; ++i) {
45 InstallExtension(GetProfile(0), i);
46 InstallExtension(verifier(), i);
47 }
48
49 ASSERT_TRUE(SetupSync());
50 ASSERT_TRUE(AllProfilesHaveSameExtensionsAsVerifier());
51 }
52
IN_PROC_BROWSER_TEST_F(SingleClientExtensionsSyncTest,InstallSomeExtensions)53 IN_PROC_BROWSER_TEST_F(SingleClientExtensionsSyncTest, InstallSomeExtensions) {
54 ASSERT_TRUE(SetupSync());
55
56 const int kNumExtensions = 5;
57 for (int i = 0; i < kNumExtensions; ++i) {
58 InstallExtension(GetProfile(0), i);
59 InstallExtension(verifier(), i);
60 }
61
62 ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
63 ASSERT_TRUE(AllProfilesHaveSameExtensionsAsVerifier());
64 }
65
66 // Helper function for waiting to see the extension count in a profile
67 // become a specific number.
ExtensionCountCheck(Profile * profile,size_t expected_count)68 static bool ExtensionCountCheck(Profile* profile, size_t expected_count) {
69 return GetInstalledExtensions(profile).size() == expected_count;
70 }
71
72 // Tests the case of an uninstall from the server conflicting with a local
73 // modification, which we expect to be resolved in favor of the uninstall.
IN_PROC_BROWSER_TEST_F(SingleClientExtensionsSyncTest,UninstallWinsConflicts)74 IN_PROC_BROWSER_TEST_F(SingleClientExtensionsSyncTest, UninstallWinsConflicts) {
75 ASSERT_TRUE(SetupClients());
76
77 // Start with an extension installed, and setup sync.
78 InstallExtensionForAllProfiles(0);
79 ASSERT_TRUE(SetupSync());
80 ASSERT_TRUE(AllProfilesHaveSameExtensionsAsVerifier());
81
82 // Simulate a delete at the server.
83 std::vector<sync_pb::SyncEntity> server_extensions =
84 GetFakeServer()->GetSyncEntitiesByModelType(syncer::EXTENSIONS);
85 ASSERT_EQ(1ul, server_extensions.size());
86 std::unique_ptr<syncer::LoopbackServerEntity> tombstone(
87 syncer::PersistentTombstoneEntity::CreateNew(
88 server_extensions[0].id_string(),
89 server_extensions[0].client_defined_unique_tag()));
90 GetFakeServer()->InjectEntity(std::move(tombstone));
91
92 // Modify the extension in the local profile to cause a conflict.
93 DisableExtension(GetProfile(0), 0);
94 ASSERT_EQ(1u, GetInstalledExtensions(GetProfile(0)).size());
95
96 // Expect the extension to get uninstalled locally.
97 AwaitMatchStatusChangeChecker checker(
98 base::BindRepeating(&ExtensionCountCheck, GetProfile(0), 0u),
99 "Waiting for profile to have no extensions");
100 EXPECT_TRUE(checker.Wait());
101 EXPECT_TRUE(GetInstalledExtensions(GetProfile(0)).empty());
102
103 // Expect the extension to remain uninstalled at the server.
104 server_extensions =
105 GetFakeServer()->GetSyncEntitiesByModelType(syncer::EXTENSIONS);
106 EXPECT_EQ(0ul, server_extensions.size());
107 }
108
109 } // namespace
110