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
3 // found in the LICENSE file.
4
5 #include "components/password_manager/core/browser/password_bubble_experiment.h"
6
7 #include <ostream>
8
9 #include "base/strings/string_number_conversions.h"
10 #include "base/test/scoped_feature_list.h"
11 #include "components/password_manager/core/common/password_manager_features.h"
12 #include "components/password_manager/core/common/password_manager_pref_names.h"
13 #include "components/prefs/pref_registry_simple.h"
14 #include "components/prefs/pref_service.h"
15 #include "components/prefs/testing_pref_service.h"
16 #include "components/signin/public/base/signin_pref_names.h"
17 #include "components/signin/public/identity_manager/identity_manager.h"
18 #include "components/sync/base/model_type.h"
19 #include "components/sync/driver/test_sync_service.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace password_bubble_experiment {
24
25 namespace {
26
27 enum class CustomPassphraseState { NONE, SET };
28
29 } // namespace
30
31 class PasswordManagerPasswordBubbleExperimentTest : public testing::Test {
32 public:
PasswordManagerPasswordBubbleExperimentTest()33 PasswordManagerPasswordBubbleExperimentTest() {
34 RegisterPrefs(pref_service_.registry());
35 signin::IdentityManager::RegisterProfilePrefs(pref_service_.registry());
36 }
37
prefs()38 PrefService* prefs() { return &pref_service_; }
39
sync_service()40 syncer::TestSyncService* sync_service() { return &fake_sync_service_; }
41
42 protected:
SetupFakeSyncServiceForTestCase(syncer::ModelType type,CustomPassphraseState passphrase_state)43 void SetupFakeSyncServiceForTestCase(syncer::ModelType type,
44 CustomPassphraseState passphrase_state) {
45 sync_service()->SetPreferredDataTypes({type});
46 sync_service()->SetActiveDataTypes({type});
47 sync_service()->SetIsUsingSecondaryPassphrase(passphrase_state ==
48 CustomPassphraseState::SET);
49 }
50
51 private:
52 syncer::TestSyncService fake_sync_service_;
53 TestingPrefServiceSimple pref_service_;
54 };
55
TEST_F(PasswordManagerPasswordBubbleExperimentTest,ShouldShowChromeSignInPasswordPromo)56 TEST_F(PasswordManagerPasswordBubbleExperimentTest,
57 ShouldShowChromeSignInPasswordPromo) {
58 // By default the promo is off.
59 EXPECT_FALSE(ShouldShowChromeSignInPasswordPromo(prefs(), nullptr));
60 constexpr struct {
61 bool account_storage_enabled;
62 bool was_already_clicked;
63 bool is_sync_allowed;
64 bool is_first_setup_complete;
65 bool is_signin_allowed;
66 int current_shown_count;
67 bool result;
68 } kTestData[] = {
69 {false, false, true, false, true, 0, true},
70 {true, false, true, false, true, 0, false},
71 {false, false, true, false, true, 5, false},
72 {false, true, true, false, true, 0, false},
73 {false, true, true, false, true, 10, false},
74 {false, false, false, false, true, 0, false},
75 {false, false, true, true, true, 0, false},
76 {false, false, true, false, false, 0, false},
77 };
78 for (const auto& test_case : kTestData) {
79 SCOPED_TRACE(testing::Message("#test_case = ") << (&test_case - kTestData));
80 base::test::ScopedFeatureList account_storage_feature;
81 account_storage_feature.InitWithFeatureState(
82 password_manager::features::kEnablePasswordsAccountStorage,
83 test_case.account_storage_enabled);
84 prefs()->SetBoolean(password_manager::prefs::kWasSignInPasswordPromoClicked,
85 test_case.was_already_clicked);
86 prefs()->SetInteger(
87 password_manager::prefs::kNumberSignInPasswordPromoShown,
88 test_case.current_shown_count);
89 sync_service()->SetDisableReasons(
90 test_case.is_sync_allowed
91 ? syncer::SyncService::DisableReasonSet()
92 : syncer::SyncService::DISABLE_REASON_PLATFORM_OVERRIDE);
93 sync_service()->SetFirstSetupComplete(test_case.is_first_setup_complete);
94 sync_service()->SetTransportState(
95 test_case.is_first_setup_complete
96 ? syncer::SyncService::TransportState::ACTIVE
97 : syncer::SyncService::TransportState::
98 PENDING_DESIRED_CONFIGURATION);
99 prefs()->SetBoolean(prefs::kSigninAllowed, test_case.is_signin_allowed);
100 #if defined(OS_CHROMEOS)
101 EXPECT_FALSE(ShouldShowChromeSignInPasswordPromo(prefs(), sync_service()));
102 #else
103 EXPECT_EQ(test_case.result,
104 ShouldShowChromeSignInPasswordPromo(prefs(), sync_service()));
105 #endif
106 }
107 }
108
109 #if !defined(OS_CHROMEOS)
TEST_F(PasswordManagerPasswordBubbleExperimentTest,ReviveSignInPasswordPromo)110 TEST_F(PasswordManagerPasswordBubbleExperimentTest, ReviveSignInPasswordPromo) {
111 sync_service()->SetDisableReasons(syncer::SyncService::DisableReasonSet());
112 sync_service()->SetFirstSetupComplete(false);
113 sync_service()->SetTransportState(
114 syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION);
115 prefs()->SetBoolean(password_manager::prefs::kWasSignInPasswordPromoClicked,
116 true);
117 prefs()->SetInteger(password_manager::prefs::kNumberSignInPasswordPromoShown,
118 10);
119
120 // The state is to be reset.
121 EXPECT_TRUE(ShouldShowChromeSignInPasswordPromo(prefs(), sync_service()));
122 }
123 #endif
124
TEST_F(PasswordManagerPasswordBubbleExperimentTest,IsSmartLockUser)125 TEST_F(PasswordManagerPasswordBubbleExperimentTest, IsSmartLockUser) {
126 constexpr struct {
127 syncer::ModelType type;
128 CustomPassphraseState passphrase_state;
129 bool expected_sync_user;
130 } kTestData[] = {
131 {syncer::ModelType::BOOKMARKS, CustomPassphraseState::NONE, false},
132 {syncer::ModelType::BOOKMARKS, CustomPassphraseState::SET, false},
133 {syncer::ModelType::PASSWORDS, CustomPassphraseState::NONE, true},
134 {syncer::ModelType::PASSWORDS, CustomPassphraseState::SET, true},
135 };
136 for (const auto& test_case : kTestData) {
137 SCOPED_TRACE(testing::Message("#test_case = ") << (&test_case - kTestData));
138 SetupFakeSyncServiceForTestCase(test_case.type, test_case.passphrase_state);
139
140 EXPECT_EQ(test_case.expected_sync_user, IsSmartLockUser(sync_service()));
141 }
142 }
143
144 } // namespace password_bubble_experiment
145