1 // Copyright 2014 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.
5 #include "chrome/browser/signin/signin_error_notifier_ash.h"
7 #include "ash/test/ash_test_base.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/notifications/notification.h"
11 #include "chrome/browser/notifications/notification_ui_manager.h"
12 #include "chrome/browser/signin/fake_signin_manager.h"
13 #include "chrome/browser/signin/signin_error_controller_factory.h"
14 #include "chrome/browser/signin/signin_error_notifier_factory_ash.h"
15 #include "chrome/browser/signin/signin_manager_factory.h"
16 #include "chrome/test/base/testing_browser_process.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "chrome/test/base/testing_profile_manager.h"
19 #include "components/signin/core/browser/fake_auth_status_provider.h"
20 #include "components/signin/core/browser/signin_error_controller.h"
21 #include "components/signin/core/browser/signin_manager.h"
22 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "ui/message_center/notification.h"
27 #include "chrome/browser/ui/ash/ash_util.h"
28 #include "ui/aura/test/test_screen.h"
29 #include "ui/gfx/screen.h"
30 #include "ui/gfx/screen_type_delegate.h"
38 static const char kTestAccountId
[] = "testuser@test.com";
39 static const char kTestUsername
[] = "testuser@test.com";
41 // Notification ID corresponding to kProfileSigninNotificationId +
43 static const std::string kNotificationId
=
44 "chrome://settings/signin/testuser@test.com";
48 class ScreenTypeDelegateDesktop
: public gfx::ScreenTypeDelegate
{
50 ScreenTypeDelegateDesktop() {}
51 virtual gfx::ScreenType
GetScreenTypeForNativeView(
52 gfx::NativeView view
) override
{
53 return chrome::IsNativeViewInAsh(view
) ?
54 gfx::SCREEN_TYPE_ALTERNATE
:
55 gfx::SCREEN_TYPE_NATIVE
;
58 DISALLOW_COPY_AND_ASSIGN(ScreenTypeDelegateDesktop
);
62 class SigninErrorNotifierTest
: public AshTestBase
{
64 void SetUp() override
{
65 // Create a signed-in profile.
66 TestingProfile::Builder builder
;
67 builder
.AddTestingFactory(SigninManagerFactory::GetInstance(),
68 FakeSigninManagerBase::Build
);
69 profile_
= builder
.Build();
70 profile_
->set_profile_name(kTestAccountId
);
72 profile_manager_
.reset(
73 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
74 ASSERT_TRUE(profile_manager_
->SetUp());
76 TestingBrowserProcess::GetGlobal();
79 // Set up screen for Windows.
81 test_screen_
.reset(aura::TestScreen::Create(gfx::Size()));
82 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE
, test_screen_
.get());
83 gfx::Screen::SetScreenTypeDelegate(&screen_type_delegate_
);
86 error_controller_
= SigninErrorControllerFactory::GetForProfile(
88 SigninErrorNotifierFactory::GetForProfile(profile_
.get());
89 notification_ui_manager_
= g_browser_process
->notification_ui_manager();
92 void TearDown() override
{
94 gfx::Screen::SetScreenTypeDelegate(nullptr);
95 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE
, nullptr);
98 profile_manager_
.reset();
100 AshTestBase::TearDown();
104 void GetMessage(base::string16
* message
) {
105 const Notification
* notification
=
106 g_browser_process
->notification_ui_manager()->FindById(
108 NotificationUIManager::GetProfileID(profile_
.get()));
109 ASSERT_FALSE(notification
== NULL
);
110 *message
= notification
->message();
114 ScreenTypeDelegateDesktop screen_type_delegate_
;
115 scoped_ptr
<gfx::Screen
> test_screen_
;
117 scoped_ptr
<TestingProfileManager
> profile_manager_
;
118 scoped_ptr
<TestingProfile
> profile_
;
119 SigninErrorController
* error_controller_
;
120 NotificationUIManager
* notification_ui_manager_
;
123 TEST_F(SigninErrorNotifierTest
, NoErrorAuthStatusProviders
) {
124 ASSERT_FALSE(notification_ui_manager_
->FindById(
125 kNotificationId
, NotificationUIManager::GetProfileID(profile_
.get())));
127 // Add a provider (removes itself on exiting this scope).
128 FakeAuthStatusProvider
provider(error_controller_
);
129 ASSERT_FALSE(notification_ui_manager_
->FindById(
130 kNotificationId
, NotificationUIManager::GetProfileID(profile_
.get())));
132 ASSERT_FALSE(notification_ui_manager_
->FindById(
133 kNotificationId
, NotificationUIManager::GetProfileID(profile_
.get())));
137 // Disabled on Win due to flake. http://crbug.com/372236
138 TEST_F(SigninErrorNotifierTest
, ErrorAuthStatusProvider
) {
140 FakeAuthStatusProvider
provider(error_controller_
);
141 ASSERT_FALSE(notification_ui_manager_
->FindById(
142 kNotificationId
, NotificationUIManager::GetProfileID(profile_
.get())));
144 FakeAuthStatusProvider
error_provider(error_controller_
);
145 error_provider
.SetAuthError(
148 GoogleServiceAuthError(
149 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
));
150 ASSERT_TRUE(notification_ui_manager_
->FindById(
152 NotificationUIManager::GetProfileID(profile_
.get())));
154 // error_provider is removed now that we've left that scope.
155 ASSERT_FALSE(notification_ui_manager_
->FindById(
156 kNotificationId
, NotificationUIManager::GetProfileID(profile_
.get())));
158 // All providers should be removed now.
159 ASSERT_FALSE(notification_ui_manager_
->FindById(
160 kNotificationId
, NotificationUIManager::GetProfileID(profile_
.get())));
165 // Test started crashing on Win 7. http://crbug.com/372277
166 #define MAYBE_AuthStatusProviderErrorTransition \
167 DISABLED_AuthStatusProviderErrorTransition
169 #define MAYBE_AuthStatusProviderErrorTransition \
170 AuthStatusProviderErrorTransition
172 TEST_F(SigninErrorNotifierTest
, MAYBE_AuthStatusProviderErrorTransition
) {
174 FakeAuthStatusProvider
provider0(error_controller_
);
175 FakeAuthStatusProvider
provider1(error_controller_
);
176 provider0
.SetAuthError(
179 GoogleServiceAuthError(
180 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
));
181 ASSERT_TRUE(notification_ui_manager_
->FindById(
182 kNotificationId
, NotificationUIManager::GetProfileID(profile_
.get())));
184 base::string16 message
;
185 GetMessage(&message
);
186 ASSERT_FALSE(message
.empty());
188 // Now set another auth error and clear the original.
189 provider1
.SetAuthError(
192 GoogleServiceAuthError(
193 GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE
));
194 provider0
.SetAuthError(
197 GoogleServiceAuthError::AuthErrorNone());
199 ASSERT_TRUE(notification_ui_manager_
->FindById(
200 kNotificationId
, NotificationUIManager::GetProfileID(profile_
.get())));
202 base::string16 new_message
;
203 GetMessage(&new_message
);
204 ASSERT_FALSE(new_message
.empty());
206 ASSERT_NE(new_message
, message
);
208 provider1
.SetAuthError(
209 kTestAccountId
, kTestUsername
, GoogleServiceAuthError::AuthErrorNone());
210 ASSERT_FALSE(notification_ui_manager_
->FindById(
211 kNotificationId
, NotificationUIManager::GetProfileID(profile_
.get())));
216 // Disabled on Win due to flake. http://crbug.com/372236
217 // Verify that SigninErrorNotifier ignores certain errors.
218 TEST_F(SigninErrorNotifierTest
, AuthStatusEnumerateAllErrors
) {
220 GoogleServiceAuthError::State error_state
;
224 ErrorTableEntry table
[] = {
225 { GoogleServiceAuthError::NONE
, false },
226 { GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
, true },
227 { GoogleServiceAuthError::USER_NOT_SIGNED_UP
, true },
228 { GoogleServiceAuthError::CONNECTION_FAILED
, false },
229 { GoogleServiceAuthError::CAPTCHA_REQUIRED
, true },
230 { GoogleServiceAuthError::ACCOUNT_DELETED
, true },
231 { GoogleServiceAuthError::ACCOUNT_DISABLED
, true },
232 { GoogleServiceAuthError::SERVICE_UNAVAILABLE
, true },
233 { GoogleServiceAuthError::TWO_FACTOR
, true },
234 { GoogleServiceAuthError::REQUEST_CANCELED
, true },
235 { GoogleServiceAuthError::HOSTED_NOT_ALLOWED
, true },
236 { GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE
, true },
237 { GoogleServiceAuthError::SERVICE_ERROR
, true },
238 { GoogleServiceAuthError::WEB_LOGIN_REQUIRED
, true },
240 static_assert(arraysize(table
) == GoogleServiceAuthError::NUM_STATES
,
241 "table size should match number of auth error types");
243 for (size_t i
= 0; i
< arraysize(table
); ++i
) {
244 FakeAuthStatusProvider
provider(error_controller_
);
245 provider
.SetAuthError(kTestAccountId
,
247 GoogleServiceAuthError(table
[i
].error_state
));
248 const Notification
* notification
= notification_ui_manager_
->FindById(
249 kNotificationId
, NotificationUIManager::GetProfileID(profile_
.get()));
250 ASSERT_EQ(table
[i
].is_error
, notification
!= NULL
);
251 if (table
[i
].is_error
) {
252 EXPECT_FALSE(notification
->title().empty());
253 EXPECT_FALSE(notification
->message().empty());
254 EXPECT_EQ((size_t)1, notification
->buttons().size());