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/profile_oauth2_token_service_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/browser/ui/ash/test_views_delegate_with_parent.h"
17 #include "chrome/test/base/testing_browser_process.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "chrome/test/base/testing_profile_manager.h"
20 #include "components/signin/core/browser/fake_auth_status_provider.h"
21 #include "components/signin/core/browser/profile_oauth2_token_service.h"
22 #include "components/signin/core/browser/signin_error_controller.h"
23 #include "components/signin/core/browser/signin_manager.h"
24 #include "content/public/test/test_browser_thread_bundle.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "ui/message_center/notification.h"
28 #if !defined(OS_CHROMEOS)
29 #include "chrome/browser/ui/ash/ash_util.h"
30 #include "ui/aura/test/test_screen.h"
31 #include "ui/gfx/screen.h"
32 #include "ui/gfx/screen_type_delegate.h"
40 static const char kTestAccountId
[] = "testuser@test.com";
42 // Notification ID corresponding to kProfileSigninNotificationId +
44 static const std::string kNotificationId
=
45 "chrome://settings/signin/testuser@test.com";
48 #if !defined(OS_CHROMEOS)
49 class ScreenTypeDelegateDesktop
: public gfx::ScreenTypeDelegate
{
51 ScreenTypeDelegateDesktop() {}
52 virtual gfx::ScreenType
GetScreenTypeForNativeView(
53 gfx::NativeView view
) OVERRIDE
{
54 return chrome::IsNativeViewInAsh(view
) ?
55 gfx::SCREEN_TYPE_ALTERNATE
:
56 gfx::SCREEN_TYPE_NATIVE
;
59 DISALLOW_COPY_AND_ASSIGN(ScreenTypeDelegateDesktop
);
63 class SigninErrorNotifierTest
: public AshTestBase
{
65 virtual void SetUp() OVERRIDE
{
66 views::ViewsDelegate::views_delegate
= &views_delegate_
;
68 // Create a signed-in profile.
69 TestingProfile::Builder builder
;
70 builder
.AddTestingFactory(SigninManagerFactory::GetInstance(),
71 FakeSigninManagerBase::Build
);
72 profile_
= builder
.Build();
73 profile_
->set_profile_name(kTestAccountId
);
75 profile_manager_
.reset(
76 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
77 ASSERT_TRUE(profile_manager_
->SetUp());
79 TestingBrowserProcess::GetGlobal();
82 // Set up screen for Windows.
83 #if !defined(OS_CHROMEOS)
84 aura::TestScreen
* test_screen
= aura::TestScreen::Create();
85 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE
, test_screen
);
86 gfx::Screen::SetScreenTypeDelegate(new ScreenTypeDelegateDesktop
);
90 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_
.get())->
91 signin_error_controller();
92 SigninErrorNotifierFactory::GetForProfile(profile_
.get());
93 notification_ui_manager_
= g_browser_process
->notification_ui_manager();
96 virtual void TearDown() OVERRIDE
{
97 profile_manager_
.reset();
99 AshTestBase::TearDown();
103 void GetMessage(base::string16
* message
) {
104 const Notification
* notification
=
105 g_browser_process
->notification_ui_manager()->FindById(kNotificationId
);
106 ASSERT_FALSE(notification
== NULL
);
107 *message
= notification
->message();
110 scoped_ptr
<TestingProfileManager
> profile_manager_
;
111 scoped_ptr
<TestingProfile
> profile_
;
112 SigninErrorController
* error_controller_
;
113 NotificationUIManager
* notification_ui_manager_
;
114 TestViewsDelegateWithParent views_delegate_
;
117 TEST_F(SigninErrorNotifierTest
, NoErrorAuthStatusProviders
) {
118 ASSERT_FALSE(notification_ui_manager_
->FindById(kNotificationId
));
120 // Add a provider (removes itself on exiting this scope).
121 FakeAuthStatusProvider
provider(error_controller_
);
122 ASSERT_FALSE(notification_ui_manager_
->FindById(kNotificationId
));
124 ASSERT_FALSE(notification_ui_manager_
->FindById(kNotificationId
));
128 // Disabled on Win due to flake. http://crbug.com/372236
129 TEST_F(SigninErrorNotifierTest
, ErrorAuthStatusProvider
) {
131 FakeAuthStatusProvider
provider(error_controller_
);
132 ASSERT_FALSE(notification_ui_manager_
->FindById(kNotificationId
));
134 FakeAuthStatusProvider
error_provider(error_controller_
);
135 error_provider
.SetAuthError(kTestAccountId
, GoogleServiceAuthError(
136 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
));
137 ASSERT_TRUE(notification_ui_manager_
->FindById(kNotificationId
));
139 // error_provider is removed now that we've left that scope.
140 ASSERT_FALSE(notification_ui_manager_
->FindById(kNotificationId
));
142 // All providers should be removed now.
143 ASSERT_FALSE(notification_ui_manager_
->FindById(kNotificationId
));
148 // Test started crashing on Win 7. http://crbug.com/372277
149 #define MAYBE_AuthStatusProviderErrorTransition \
150 DISABLED_AuthStatusProviderErrorTransition
152 #define MAYBE_AuthStatusProviderErrorTransition \
153 AuthStatusProviderErrorTransition
155 TEST_F(SigninErrorNotifierTest
, MAYBE_AuthStatusProviderErrorTransition
) {
157 FakeAuthStatusProvider
provider0(error_controller_
);
158 FakeAuthStatusProvider
provider1(error_controller_
);
159 provider0
.SetAuthError(
161 GoogleServiceAuthError(
162 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
));
163 ASSERT_TRUE(notification_ui_manager_
->FindById(kNotificationId
));
165 base::string16 message
;
166 GetMessage(&message
);
167 ASSERT_FALSE(message
.empty());
169 // Now set another auth error and clear the original.
170 provider1
.SetAuthError(
172 GoogleServiceAuthError(
173 GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE
));
174 provider0
.SetAuthError(
175 kTestAccountId
, GoogleServiceAuthError::AuthErrorNone());
177 ASSERT_TRUE(notification_ui_manager_
->FindById(kNotificationId
));
179 base::string16 new_message
;
180 GetMessage(&new_message
);
181 ASSERT_FALSE(new_message
.empty());
183 ASSERT_NE(new_message
, message
);
185 provider1
.SetAuthError(
186 kTestAccountId
, GoogleServiceAuthError::AuthErrorNone());
187 ASSERT_FALSE(notification_ui_manager_
->FindById(kNotificationId
));
192 // Disabled on Win due to flake. http://crbug.com/372236
193 // Verify that SigninErrorNotifier ignores certain errors.
194 TEST_F(SigninErrorNotifierTest
, AuthStatusEnumerateAllErrors
) {
196 GoogleServiceAuthError::State error_state
;
200 ErrorTableEntry table
[] = {
201 { GoogleServiceAuthError::NONE
, false },
202 { GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
, true },
203 { GoogleServiceAuthError::USER_NOT_SIGNED_UP
, true },
204 { GoogleServiceAuthError::CONNECTION_FAILED
, false },
205 { GoogleServiceAuthError::CAPTCHA_REQUIRED
, true },
206 { GoogleServiceAuthError::ACCOUNT_DELETED
, true },
207 { GoogleServiceAuthError::ACCOUNT_DISABLED
, true },
208 { GoogleServiceAuthError::SERVICE_UNAVAILABLE
, true },
209 { GoogleServiceAuthError::TWO_FACTOR
, true },
210 { GoogleServiceAuthError::REQUEST_CANCELED
, true },
211 { GoogleServiceAuthError::HOSTED_NOT_ALLOWED
, true },
212 { GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE
, true },
213 { GoogleServiceAuthError::SERVICE_ERROR
, true },
215 COMPILE_ASSERT(ARRAYSIZE_UNSAFE(table
) == GoogleServiceAuthError::NUM_STATES
,
216 kTable_size_does_not_match_number_of_auth_error_types
);
218 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(table
); ++i
) {
219 FakeAuthStatusProvider
provider(error_controller_
);
220 provider
.SetAuthError(kTestAccountId
,
221 GoogleServiceAuthError(table
[i
].error_state
));
222 const Notification
* notification
= notification_ui_manager_
->
223 FindById(kNotificationId
);
224 ASSERT_EQ(table
[i
].is_error
, notification
!= NULL
);
225 if (table
[i
].is_error
) {
226 EXPECT_FALSE(notification
->title().empty());
227 EXPECT_FALSE(notification
->message().empty());
228 EXPECT_EQ((size_t)1, notification
->buttons().size());