1 // Copyright (c) 2013 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 "chrome/browser/signin/signin_global_error.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <string>
11
12 #include "base/bind.h"
13 #include "base/stl_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/test/metrics/histogram_tester.h"
16 #include "chrome/browser/profiles/profile_attributes_entry.h"
17 #include "chrome/browser/profiles/profile_attributes_storage.h"
18 #include "chrome/browser/profiles/profile_manager.h"
19 #include "chrome/browser/profiles/profile_metrics.h"
20 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
21 #include "chrome/browser/signin/signin_error_controller_factory.h"
22 #include "chrome/browser/signin/signin_global_error_factory.h"
23 #include "chrome/browser/ui/global_error/global_error_service.h"
24 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/test/base/testing_browser_process.h"
27 #include "chrome/test/base/testing_profile.h"
28 #include "chrome/test/base/testing_profile_manager.h"
29 #include "components/prefs/pref_service.h"
30 #include "components/signin/core/browser/signin_error_controller.h"
31 #include "components/signin/public/identity_manager/identity_test_environment.h"
32 #include "components/signin/public/identity_manager/identity_test_utils.h"
33 #include "components/sync_preferences/pref_service_syncable.h"
34 #include "content/public/test/browser_task_environment.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36
37 static const char kTestEmail[] = "testuser@test.com";
38
39 class SigninGlobalErrorTest : public testing::Test {
40 public:
SigninGlobalErrorTest()41 SigninGlobalErrorTest() :
42 profile_manager_(TestingBrowserProcess::GetGlobal()) {}
43
SetUp()44 void SetUp() override {
45 ASSERT_TRUE(profile_manager_.SetUp());
46
47 // Create a signed-in profile.
48 TestingProfile::TestingFactories testing_factories =
49 IdentityTestEnvironmentProfileAdaptor::
50 GetIdentityTestEnvironmentFactories();
51
52 profile_ = profile_manager_.CreateTestingProfile(
53 "Person 1", std::unique_ptr<sync_preferences::PrefServiceSyncable>(),
54 base::UTF8ToUTF16("Person 1"), 0, std::string(),
55 std::move(testing_factories));
56
57 identity_test_env_profile_adaptor_ =
58 std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile());
59
60 AccountInfo account_info =
61 identity_test_env_profile_adaptor_->identity_test_env()
62 ->MakePrimaryAccountAvailable(kTestEmail);
63 ProfileAttributesEntry* entry;
64 ASSERT_TRUE(profile_manager_.profile_attributes_storage()->
65 GetProfileAttributesWithPath(profile()->GetPath(), &entry));
66
67 entry->SetAuthInfo(account_info.gaia, base::UTF8ToUTF16(kTestEmail),
68 /*is_consented_primary_account=*/true);
69
70 global_error_ = SigninGlobalErrorFactory::GetForProfile(profile());
71 error_controller_ = SigninErrorControllerFactory::GetForProfile(profile());
72 }
73
profile()74 TestingProfile* profile() { return profile_; }
testing_profile_manager()75 TestingProfileManager* testing_profile_manager() {
76 return &profile_manager_;
77 }
78
global_error()79 SigninGlobalError* global_error() { return global_error_; }
error_controller()80 SigninErrorController* error_controller() { return error_controller_; }
81
SetAuthError(GoogleServiceAuthError::State state)82 void SetAuthError(GoogleServiceAuthError::State state) {
83 signin::IdentityTestEnvironment* identity_test_env =
84 identity_test_env_profile_adaptor_->identity_test_env();
85 CoreAccountId primary_account_id =
86 identity_test_env->identity_manager()->GetPrimaryAccountId();
87
88 signin::UpdatePersistentErrorOfRefreshTokenForAccount(
89 identity_test_env->identity_manager(), primary_account_id,
90 GoogleServiceAuthError(state));
91 }
92
93 private:
94 content::BrowserTaskEnvironment task_environment_;
95 TestingProfileManager profile_manager_;
96 TestingProfile* profile_;
97
98 std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
99 identity_test_env_profile_adaptor_;
100
101 SigninGlobalError* global_error_;
102 SigninErrorController* error_controller_;
103 };
104
TEST_F(SigninGlobalErrorTest,Basic)105 TEST_F(SigninGlobalErrorTest, Basic) {
106 ASSERT_FALSE(global_error()->HasMenuItem());
107
108 SetAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
109 EXPECT_TRUE(global_error()->HasMenuItem());
110
111 SetAuthError(GoogleServiceAuthError::NONE);
112 EXPECT_FALSE(global_error()->HasMenuItem());
113 }
114
115 // Verify that SigninGlobalError ignores certain errors.
TEST_F(SigninGlobalErrorTest,AuthStatusEnumerateAllErrors)116 TEST_F(SigninGlobalErrorTest, AuthStatusEnumerateAllErrors) {
117 typedef struct {
118 GoogleServiceAuthError::State error_state;
119 bool is_error;
120 } ErrorTableEntry;
121
122 ErrorTableEntry table[] = {
123 {GoogleServiceAuthError::NONE, false},
124 {GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, true},
125 {GoogleServiceAuthError::USER_NOT_SIGNED_UP, true},
126 {GoogleServiceAuthError::CONNECTION_FAILED, false},
127 {GoogleServiceAuthError::SERVICE_UNAVAILABLE, false},
128 {GoogleServiceAuthError::REQUEST_CANCELED, false},
129 {GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE, true},
130 {GoogleServiceAuthError::SERVICE_ERROR, true},
131 };
132 static_assert(
133 base::size(table) == GoogleServiceAuthError::NUM_STATES -
134 GoogleServiceAuthError::kDeprecatedStateCount,
135 "table size should match number of auth error types");
136
137 // Mark the profile with an active timestamp so profile_metrics logs it.
138 testing_profile_manager()->UpdateLastUser(profile());
139
140 for (ErrorTableEntry entry : table) {
141 SetAuthError(GoogleServiceAuthError::NONE);
142
143 base::HistogramTester histogram_tester;
144 SetAuthError(entry.error_state);
145
146 EXPECT_EQ(global_error()->HasMenuItem(), entry.is_error);
147 EXPECT_EQ(global_error()->MenuItemLabel().empty(), !entry.is_error);
148 EXPECT_EQ(global_error()->GetBubbleViewMessages().empty(), !entry.is_error);
149 EXPECT_FALSE(global_error()->GetBubbleViewTitle().empty());
150 EXPECT_FALSE(global_error()->GetBubbleViewAcceptButtonLabel().empty());
151 EXPECT_TRUE(global_error()->GetBubbleViewCancelButtonLabel().empty());
152
153 ProfileMetrics::LogNumberOfProfiles(&testing_profile_manager()
154 ->profile_manager()
155 ->GetProfileAttributesStorage());
156
157 if (entry.is_error) {
158 histogram_tester.ExpectBucketCount("Signin.AuthError", entry.error_state,
159 1);
160 }
161 histogram_tester.ExpectBucketCount("Profile.NumberOfProfilesWithAuthErrors",
162 entry.is_error, 1);
163 }
164 }
165