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