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/ui/browser.h"
14 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
15 #include "chrome/browser/ui/webui/signin/login_ui_service_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/sync_driver/sync_error_controller.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "ui/message_center/notification.h"
25 #include "chrome/browser/ui/ash/ash_util.h"
26 #include "ui/aura/test/test_screen.h"
27 #include "ui/gfx/screen.h"
28 #include "ui/gfx/screen_type_delegate.h"
31 using ::testing::NiceMock
;
32 using ::testing::Return
;
33 using ::testing::ReturnRef
;
41 static const char kTestAccountId
[] = "testuser@test.com";
43 // Notification ID corresponding to kProfileSyncNotificationId + kTestAccountId.
44 static const std::string kNotificationId
=
45 "chrome://settings/sync/testuser@test.com";
48 class ScreenTypeDelegateDesktop
: public gfx::ScreenTypeDelegate
{
50 ScreenTypeDelegateDesktop() {}
51 ~ScreenTypeDelegateDesktop() override
{}
52 gfx::ScreenType
GetScreenTypeForNativeView(gfx::NativeView view
) override
{
53 return chrome::IsNativeViewInAsh(view
) ?
54 gfx::SCREEN_TYPE_ALTERNATE
:
55 gfx::SCREEN_TYPE_NATIVE
;
59 DISALLOW_COPY_AND_ASSIGN(ScreenTypeDelegateDesktop
);
63 class FakeLoginUIService
: public LoginUIService
{
65 FakeLoginUIService() : LoginUIService(NULL
) {}
66 ~FakeLoginUIService() override
{}
69 class FakeLoginUI
: public LoginUIService::LoginUI
{
71 FakeLoginUI() : focus_ui_call_count_(0) {}
73 ~FakeLoginUI() override
{}
75 int focus_ui_call_count() const { return focus_ui_call_count_
; }
78 // LoginUIService::LoginUI:
79 void FocusUI() override
{ ++focus_ui_call_count_
; }
80 void CloseUI() override
{}
82 int focus_ui_call_count_
;
85 scoped_ptr
<KeyedService
> BuildMockLoginUIService(
86 content::BrowserContext
* profile
) {
87 return make_scoped_ptr(new FakeLoginUIService());
90 class SyncErrorNotifierTest
: public AshTestBase
{
92 SyncErrorNotifierTest() {}
93 ~SyncErrorNotifierTest() override
{}
95 void SetUp() override
{
96 profile_manager_
.reset(
97 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
98 ASSERT_TRUE(profile_manager_
->SetUp());
100 profile_
= profile_manager_
->CreateTestingProfile(kTestAccountId
);
102 TestingBrowserProcess::GetGlobal();
103 AshTestBase::SetUp();
105 // Set up a desktop screen for Windows to hold native widgets, used when
106 // adding desktop widgets (i.e., message center notifications).
108 test_screen_
.reset(aura::TestScreen::Create(gfx::Size()));
109 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE
, test_screen_
.get());
110 gfx::Screen::SetScreenTypeDelegate(&screen_type_delegate_
);
113 service_
.reset(new NiceMock
<ProfileSyncServiceMock
>(profile_
));
115 FakeLoginUIService
* login_ui_service
= static_cast<FakeLoginUIService
*>(
116 LoginUIServiceFactory::GetInstance()->SetTestingFactoryAndUse(
117 profile_
, BuildMockLoginUIService
));
118 login_ui_service
->SetLoginUI(&login_ui_
);
120 error_controller_
.reset(new SyncErrorController(service_
.get()));
121 error_notifier_
.reset(new SyncErrorNotifier(error_controller_
.get(),
124 notification_ui_manager_
= g_browser_process
->notification_ui_manager();
127 void TearDown() override
{
128 error_notifier_
->Shutdown();
131 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE
, nullptr);
132 gfx::Screen::SetScreenTypeDelegate(nullptr);
133 test_screen_
.reset();
135 profile_manager_
.reset();
137 AshTestBase::TearDown();
141 // Utility function to test that SyncErrorNotifier behaves correctly for the
142 // given error condition.
143 void VerifySyncErrorNotifierResult(GoogleServiceAuthError::State error_state
,
146 EXPECT_CALL(*service_
, HasSyncSetupCompleted())
147 .WillRepeatedly(Return(is_signed_in
));
149 GoogleServiceAuthError
auth_error(error_state
);
150 EXPECT_CALL(*service_
, GetAuthError()).WillRepeatedly(
151 ReturnRef(auth_error
));
153 error_controller_
->OnStateChanged();
154 EXPECT_EQ(is_error
, error_controller_
->HasError());
156 // If there is an error we should see a notification.
157 const Notification
* notification
= notification_ui_manager_
->FindById(
158 kNotificationId
, NotificationUIManager::GetProfileID(profile_
));
160 ASSERT_TRUE(notification
);
161 ASSERT_FALSE(notification
->title().empty());
162 ASSERT_FALSE(notification
->title().empty());
163 ASSERT_EQ((size_t)1, notification
->buttons().size());
165 ASSERT_FALSE(notification
);
170 ScreenTypeDelegateDesktop screen_type_delegate_
;
171 scoped_ptr
<gfx::Screen
> test_screen_
;
173 scoped_ptr
<TestingProfileManager
> profile_manager_
;
174 scoped_ptr
<SyncErrorController
> error_controller_
;
175 scoped_ptr
<SyncErrorNotifier
> error_notifier_
;
176 scoped_ptr
<NiceMock
<ProfileSyncServiceMock
> > service_
;
177 TestingProfile
* profile_
;
178 FakeLoginUI login_ui_
;
179 NotificationUIManager
* notification_ui_manager_
;
181 DISALLOW_COPY_AND_ASSIGN(SyncErrorNotifierTest
);
186 // Test that SyncErrorNotifier shows an notification if a passphrase is
188 // Disabled on Windows: http://crbug.com/373238
190 #define MAYBE_PassphraseNotification DISABLED_PassphraseNotification
192 #define MAYBE_PassphraseNotification PassphraseNotification
194 TEST_F(SyncErrorNotifierTest
, MAYBE_PassphraseNotification
) {
195 ASSERT_FALSE(notification_ui_manager_
->FindById(
196 kNotificationId
, NotificationUIManager::GetProfileID(profile_
)));
198 browser_sync::SyncBackendHost::Status status
;
199 EXPECT_CALL(*service_
, QueryDetailedSyncStatus(_
))
200 .WillRepeatedly(Return(false));
202 EXPECT_CALL(*service_
, IsPassphraseRequired())
203 .WillRepeatedly(Return(true));
204 EXPECT_CALL(*service_
, IsPassphraseRequiredForDecryption())
205 .WillRepeatedly(Return(true));
207 SCOPED_TRACE("Expected a notification for passphrase error");
208 VerifySyncErrorNotifierResult(GoogleServiceAuthError::NONE
,
209 true /* signed in */,
213 // Check that no notification is shown if there is no error.
214 EXPECT_CALL(*service_
, IsPassphraseRequired())
215 .WillRepeatedly(Return(false));
216 EXPECT_CALL(*service_
, IsPassphraseRequiredForDecryption())
217 .WillRepeatedly(Return(false));
219 SCOPED_TRACE("Not expecting notification since no error exists");
220 VerifySyncErrorNotifierResult(GoogleServiceAuthError::NONE
,
221 true /* signed in */,
222 false /* no error */);
225 // Check that no notification is shown if sync setup is not completed.
226 EXPECT_CALL(*service_
, IsPassphraseRequired())
227 .WillRepeatedly(Return(true));
228 EXPECT_CALL(*service_
, IsPassphraseRequiredForDecryption())
229 .WillRepeatedly(Return(true));
231 SCOPED_TRACE("Not expecting notification since sync setup is incomplete");
232 VerifySyncErrorNotifierResult(
233 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
,
234 false /* not signed in */,
235 false /* no error */);