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. 4 5#include "chrome/browser/signin/signin_error_notifier_ash.h" 6 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/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/profile_oauth2_token_service.h" 21#include "components/signin/core/browser/signin_error_controller.h" 22#include "components/signin/core/browser/signin_manager.h" 23#include "content/public/test/test_browser_thread_bundle.h" 24#include "testing/gtest/include/gtest/gtest.h" 25#include "ui/message_center/notification.h" 26 27#if defined(OS_WIN) 28#include "chrome/browser/ui/ash/ash_util.h" 29#include "ui/aura/test/test_screen.h" 30#include "ui/gfx/screen.h" 31#include "ui/gfx/screen_type_delegate.h" 32#endif 33 34namespace ash { 35namespace test { 36 37namespace { 38 39static const char kTestAccountId[] = "testuser@test.com"; 40static const char kTestUsername[] = "testuser@test.com"; 41 42// Notification ID corresponding to kProfileSigninNotificationId + 43// kTestAccountId. 44static const std::string kNotificationId = 45 "chrome://settings/signin/testuser@test.com"; 46} 47 48#if defined(OS_WIN) 49class ScreenTypeDelegateDesktop : public gfx::ScreenTypeDelegate { 50 public: 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; 57 } 58 private: 59 DISALLOW_COPY_AND_ASSIGN(ScreenTypeDelegateDesktop); 60}; 61#endif 62 63class SigninErrorNotifierTest : public AshTestBase { 64 public: 65 virtual void SetUp() OVERRIDE { 66 // Create a signed-in profile. 67 TestingProfile::Builder builder; 68 builder.AddTestingFactory(SigninManagerFactory::GetInstance(), 69 FakeSigninManagerBase::Build); 70 profile_ = builder.Build(); 71 profile_->set_profile_name(kTestAccountId); 72 73 profile_manager_.reset( 74 new TestingProfileManager(TestingBrowserProcess::GetGlobal())); 75 ASSERT_TRUE(profile_manager_->SetUp()); 76 77 TestingBrowserProcess::GetGlobal(); 78 AshTestBase::SetUp(); 79 80 // Set up screen for Windows. 81#if defined(OS_WIN) 82 test_screen_.reset(aura::TestScreen::Create(gfx::Size())); 83 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen_.get()); 84 gfx::Screen::SetScreenTypeDelegate(new ScreenTypeDelegateDesktop); 85#endif 86 87 error_controller_ = 88 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())-> 89 signin_error_controller(); 90 SigninErrorNotifierFactory::GetForProfile(profile_.get()); 91 notification_ui_manager_ = g_browser_process->notification_ui_manager(); 92 } 93 94 virtual void TearDown() OVERRIDE { 95#if defined(OS_WIN) 96 test_screen_.reset(); 97#endif 98 profile_manager_.reset(); 99 100 AshTestBase::TearDown(); 101 } 102 103 protected: 104 void GetMessage(base::string16* message) { 105 const Notification* notification = 106 g_browser_process->notification_ui_manager()->FindById(kNotificationId); 107 ASSERT_FALSE(notification == NULL); 108 *message = notification->message(); 109 } 110 111#if defined(OS_WIN) 112 scoped_ptr<gfx::Screen> test_screen_; 113#endif 114 scoped_ptr<TestingProfileManager> profile_manager_; 115 scoped_ptr<TestingProfile> profile_; 116 SigninErrorController* error_controller_; 117 NotificationUIManager* notification_ui_manager_; 118}; 119 120TEST_F(SigninErrorNotifierTest, NoErrorAuthStatusProviders) { 121 ASSERT_FALSE(notification_ui_manager_->FindById(kNotificationId)); 122 { 123 // Add a provider (removes itself on exiting this scope). 124 FakeAuthStatusProvider provider(error_controller_); 125 ASSERT_FALSE(notification_ui_manager_->FindById(kNotificationId)); 126 } 127 ASSERT_FALSE(notification_ui_manager_->FindById(kNotificationId)); 128} 129 130#if !defined(OS_WIN) 131// Disabled on Win due to flake. http://crbug.com/372236 132TEST_F(SigninErrorNotifierTest, ErrorAuthStatusProvider) { 133 { 134 FakeAuthStatusProvider provider(error_controller_); 135 ASSERT_FALSE(notification_ui_manager_->FindById(kNotificationId)); 136 { 137 FakeAuthStatusProvider error_provider(error_controller_); 138 error_provider.SetAuthError( 139 kTestAccountId, 140 kTestUsername, 141 GoogleServiceAuthError( 142 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 143 ASSERT_TRUE(notification_ui_manager_->FindById(kNotificationId)); 144 } 145 // error_provider is removed now that we've left that scope. 146 ASSERT_FALSE(notification_ui_manager_->FindById(kNotificationId)); 147 } 148 // All providers should be removed now. 149 ASSERT_FALSE(notification_ui_manager_->FindById(kNotificationId)); 150} 151#endif 152 153#if defined(OS_WIN) 154// Test started crashing on Win 7. http://crbug.com/372277 155#define MAYBE_AuthStatusProviderErrorTransition \ 156 DISABLED_AuthStatusProviderErrorTransition 157#else 158#define MAYBE_AuthStatusProviderErrorTransition \ 159 AuthStatusProviderErrorTransition 160#endif 161TEST_F(SigninErrorNotifierTest, MAYBE_AuthStatusProviderErrorTransition) { 162 { 163 FakeAuthStatusProvider provider0(error_controller_); 164 FakeAuthStatusProvider provider1(error_controller_); 165 provider0.SetAuthError( 166 kTestAccountId, 167 kTestUsername, 168 GoogleServiceAuthError( 169 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 170 ASSERT_TRUE(notification_ui_manager_->FindById(kNotificationId)); 171 172 base::string16 message; 173 GetMessage(&message); 174 ASSERT_FALSE(message.empty()); 175 176 // Now set another auth error and clear the original. 177 provider1.SetAuthError( 178 kTestAccountId, 179 kTestUsername, 180 GoogleServiceAuthError( 181 GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE)); 182 provider0.SetAuthError( 183 kTestAccountId, 184 kTestUsername, 185 GoogleServiceAuthError::AuthErrorNone()); 186 187 ASSERT_TRUE(notification_ui_manager_->FindById(kNotificationId)); 188 189 base::string16 new_message; 190 GetMessage(&new_message); 191 ASSERT_FALSE(new_message.empty()); 192 193 ASSERT_NE(new_message, message); 194 195 provider1.SetAuthError( 196 kTestAccountId, kTestUsername, GoogleServiceAuthError::AuthErrorNone()); 197 ASSERT_FALSE(notification_ui_manager_->FindById(kNotificationId)); 198 } 199} 200 201#if !defined(OS_WIN) 202// Disabled on Win due to flake. http://crbug.com/372236 203// Verify that SigninErrorNotifier ignores certain errors. 204TEST_F(SigninErrorNotifierTest, AuthStatusEnumerateAllErrors) { 205 typedef struct { 206 GoogleServiceAuthError::State error_state; 207 bool is_error; 208 } ErrorTableEntry; 209 210 ErrorTableEntry table[] = { 211 { GoogleServiceAuthError::NONE, false }, 212 { GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, true }, 213 { GoogleServiceAuthError::USER_NOT_SIGNED_UP, true }, 214 { GoogleServiceAuthError::CONNECTION_FAILED, false }, 215 { GoogleServiceAuthError::CAPTCHA_REQUIRED, true }, 216 { GoogleServiceAuthError::ACCOUNT_DELETED, true }, 217 { GoogleServiceAuthError::ACCOUNT_DISABLED, true }, 218 { GoogleServiceAuthError::SERVICE_UNAVAILABLE, true }, 219 { GoogleServiceAuthError::TWO_FACTOR, true }, 220 { GoogleServiceAuthError::REQUEST_CANCELED, true }, 221 { GoogleServiceAuthError::HOSTED_NOT_ALLOWED, true }, 222 { GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE, true }, 223 { GoogleServiceAuthError::SERVICE_ERROR, true }, 224 }; 225 COMPILE_ASSERT(ARRAYSIZE_UNSAFE(table) == GoogleServiceAuthError::NUM_STATES, 226 kTable_size_does_not_match_number_of_auth_error_types); 227 228 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(table); ++i) { 229 FakeAuthStatusProvider provider(error_controller_); 230 provider.SetAuthError(kTestAccountId, 231 kTestUsername, 232 GoogleServiceAuthError(table[i].error_state)); 233 const Notification* notification = notification_ui_manager_-> 234 FindById(kNotificationId); 235 ASSERT_EQ(table[i].is_error, notification != NULL); 236 if (table[i].is_error) { 237 EXPECT_FALSE(notification->title().empty()); 238 EXPECT_FALSE(notification->message().empty()); 239 EXPECT_EQ((size_t)1, notification->buttons().size()); 240 } 241 } 242} 243#endif 244 245} // namespace test 246} // namespace ash 247