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/sync/sync_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/sync/profile_sync_service_mock.h"
13 #include "chrome/browser/sync/sync_error_controller.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
16 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/test/base/testing_browser_process.h"
19 #include "chrome/test/base/testing_profile.h"
20 #include "chrome/test/base/testing_profile_manager.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/message_center/notification.h"
25 #if !defined(OS_CHROMEOS)
26 #include "chrome/browser/ui/ash/ash_util.h"
27 #include "ui/aura/test/test_screen.h"
28 #include "ui/gfx/screen.h"
29 #include "ui/gfx/screen_type_delegate.h"
32 using ::testing::NiceMock
;
33 using ::testing::Return
;
34 using ::testing::ReturnRef
;
42 static const char kTestAccountId
[] = "testuser@test.com";
44 // Notification ID corresponding to kProfileSyncNotificationId + kTestAccountId.
45 static const std::string kNotificationId
=
46 "chrome://settings/sync/testuser@test.com";
48 #if !defined(OS_CHROMEOS)
49 class ScreenTypeDelegateDesktop
: public gfx::ScreenTypeDelegate
{
51 ScreenTypeDelegateDesktop() {}
52 virtual ~ScreenTypeDelegateDesktop() {}
53 virtual gfx::ScreenType
GetScreenTypeForNativeView(
54 gfx::NativeView view
) OVERRIDE
{
55 return chrome::IsNativeViewInAsh(view
) ?
56 gfx::SCREEN_TYPE_ALTERNATE
:
57 gfx::SCREEN_TYPE_NATIVE
;
61 DISALLOW_COPY_AND_ASSIGN(ScreenTypeDelegateDesktop
);
65 class FakeLoginUIService
: public LoginUIService
{
67 FakeLoginUIService() : LoginUIService(NULL
) {}
68 virtual ~FakeLoginUIService() {}
71 class FakeLoginUI
: public LoginUIService::LoginUI
{
73 FakeLoginUI() : focus_ui_call_count_(0) {}
75 virtual ~FakeLoginUI() {}
77 int focus_ui_call_count() const { return focus_ui_call_count_
; }
80 // LoginUIService::LoginUI:
81 virtual void FocusUI() OVERRIDE
{
82 ++focus_ui_call_count_
;
84 virtual void CloseUI() OVERRIDE
{}
86 int focus_ui_call_count_
;
89 KeyedService
* BuildMockLoginUIService(
90 content::BrowserContext
* profile
) {
91 return new FakeLoginUIService();
94 class SyncErrorNotifierTest
: public AshTestBase
{
96 SyncErrorNotifierTest() {}
97 virtual ~SyncErrorNotifierTest() {}
99 virtual void SetUp() OVERRIDE
{
100 profile_manager_
.reset(
101 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
102 ASSERT_TRUE(profile_manager_
->SetUp());
104 profile_
= profile_manager_
->CreateTestingProfile(kTestAccountId
);
106 TestingBrowserProcess::GetGlobal();
107 AshTestBase::SetUp();
109 // Set up a desktop screen for Windows to hold native widgets, used when
110 // adding desktop widgets (i.e., message center notifications).
112 aura::TestScreen
* test_screen
= aura::TestScreen::Create();
113 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE
, test_screen
);
114 gfx::Screen::SetScreenTypeDelegate(new ScreenTypeDelegateDesktop
);
117 service_
.reset(new NiceMock
<ProfileSyncServiceMock
>(profile_
));
119 FakeLoginUIService
* login_ui_service
= static_cast<FakeLoginUIService
*>(
120 LoginUIServiceFactory::GetInstance()->SetTestingFactoryAndUse(
121 profile_
, BuildMockLoginUIService
));
122 login_ui_service
->SetLoginUI(&login_ui_
);
124 error_controller_
.reset(new SyncErrorController(service_
.get()));
125 error_notifier_
.reset(new SyncErrorNotifier(error_controller_
.get(),
128 notification_ui_manager_
= g_browser_process
->notification_ui_manager();
131 virtual void TearDown() OVERRIDE
{
132 error_notifier_
->Shutdown();
134 profile_manager_
.reset();
136 AshTestBase::TearDown();
140 // Utility function to test that SyncErrorNotifier behaves correctly for the
141 // given error condition.
142 void VerifySyncErrorNotifierResult(GoogleServiceAuthError::State error_state
,
145 EXPECT_CALL(*service_
, HasSyncSetupCompleted())
146 .WillRepeatedly(Return(is_signed_in
));
148 GoogleServiceAuthError
auth_error(error_state
);
149 EXPECT_CALL(*service_
, GetAuthError()).WillRepeatedly(
150 ReturnRef(auth_error
));
152 error_controller_
->OnStateChanged();
153 EXPECT_EQ(is_error
, error_controller_
->HasError());
155 // If there is an error we should see a notification.
156 const Notification
* notification
= notification_ui_manager_
->
157 FindById(kNotificationId
);
159 ASSERT_TRUE(notification
);
160 ASSERT_FALSE(notification
->title().empty());
161 ASSERT_FALSE(notification
->title().empty());
162 ASSERT_EQ((size_t)1, notification
->buttons().size());
164 ASSERT_FALSE(notification
);
168 scoped_ptr
<TestingProfileManager
> profile_manager_
;
169 scoped_ptr
<SyncErrorController
> error_controller_
;
170 scoped_ptr
<SyncErrorNotifier
> error_notifier_
;
171 scoped_ptr
<NiceMock
<ProfileSyncServiceMock
> > service_
;
172 TestingProfile
* profile_
;
173 FakeLoginUI login_ui_
;
174 NotificationUIManager
* notification_ui_manager_
;
176 DISALLOW_COPY_AND_ASSIGN(SyncErrorNotifierTest
);
181 // Test that SyncErrorNotifier shows an notification if a passphrase is
183 // Disabled on Windows: http://crbug.com/373238
185 #define MAYBE_PassphraseNotification DISABLED_PassphraseNotification
187 #define MAYBE_PassphraseNotification PassphraseNotification
189 TEST_F(SyncErrorNotifierTest
, MAYBE_PassphraseNotification
) {
190 ASSERT_FALSE(notification_ui_manager_
->FindById(kNotificationId
));
192 browser_sync::SyncBackendHost::Status status
;
193 EXPECT_CALL(*service_
, QueryDetailedSyncStatus(_
))
194 .WillRepeatedly(Return(false));
196 EXPECT_CALL(*service_
, IsPassphraseRequired())
197 .WillRepeatedly(Return(true));
198 EXPECT_CALL(*service_
, IsPassphraseRequiredForDecryption())
199 .WillRepeatedly(Return(true));
201 SCOPED_TRACE("Expected a notification for passphrase error");
202 VerifySyncErrorNotifierResult(GoogleServiceAuthError::NONE
,
203 true /* signed in */,
207 // Check that no notification is shown if there is no error.
208 EXPECT_CALL(*service_
, IsPassphraseRequired())
209 .WillRepeatedly(Return(false));
210 EXPECT_CALL(*service_
, IsPassphraseRequiredForDecryption())
211 .WillRepeatedly(Return(false));
213 SCOPED_TRACE("Not expecting notification since no error exists");
214 VerifySyncErrorNotifierResult(GoogleServiceAuthError::NONE
,
215 true /* signed in */,
216 false /* no error */);
219 // Check that no notification is shown if sync setup is not completed.
220 EXPECT_CALL(*service_
, IsPassphraseRequired())
221 .WillRepeatedly(Return(true));
222 EXPECT_CALL(*service_
, IsPassphraseRequiredForDecryption())
223 .WillRepeatedly(Return(true));
225 SCOPED_TRACE("Not expecting notification since sync setup is incomplete");
226 VerifySyncErrorNotifierResult(
227 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
,
228 false /* not signed in */,
229 false /* no error */);