Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / sync / sync_error_notifier_ash_unittest.cc
blob1b4f5e712cb008964e09b08eedf65bae3a1cb263
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_WIN)
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"
30 #endif
32 using ::testing::NiceMock;
33 using ::testing::Return;
34 using ::testing::ReturnRef;
35 using ::testing::_;
37 namespace ash {
38 namespace test {
40 namespace {
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_WIN)
49 class ScreenTypeDelegateDesktop : public gfx::ScreenTypeDelegate {
50 public:
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;
60 private:
61 DISALLOW_COPY_AND_ASSIGN(ScreenTypeDelegateDesktop);
63 #endif
65 class FakeLoginUIService: public LoginUIService {
66 public:
67 FakeLoginUIService() : LoginUIService(NULL) {}
68 virtual ~FakeLoginUIService() {}
71 class FakeLoginUI : public LoginUIService::LoginUI {
72 public:
73 FakeLoginUI() : focus_ui_call_count_(0) {}
75 virtual ~FakeLoginUI() {}
77 int focus_ui_call_count() const { return focus_ui_call_count_; }
79 private:
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 {
95 public:
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).
111 #if defined(OS_WIN)
112 test_screen_.reset(aura::TestScreen::Create(gfx::Size()));
113 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen_.get());
114 gfx::Screen::SetScreenTypeDelegate(new ScreenTypeDelegateDesktop);
115 #endif
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(),
126 profile_));
128 notification_ui_manager_ = g_browser_process->notification_ui_manager();
131 virtual void TearDown() override {
132 error_notifier_->Shutdown();
133 service_.reset();
134 #if defined(OS_WIN)
135 test_screen_.reset();
136 #endif
137 profile_manager_.reset();
139 AshTestBase::TearDown();
142 protected:
143 // Utility function to test that SyncErrorNotifier behaves correctly for the
144 // given error condition.
145 void VerifySyncErrorNotifierResult(GoogleServiceAuthError::State error_state,
146 bool is_signed_in,
147 bool is_error) {
148 EXPECT_CALL(*service_, HasSyncSetupCompleted())
149 .WillRepeatedly(Return(is_signed_in));
151 GoogleServiceAuthError auth_error(error_state);
152 EXPECT_CALL(*service_, GetAuthError()).WillRepeatedly(
153 ReturnRef(auth_error));
155 error_controller_->OnStateChanged();
156 EXPECT_EQ(is_error, error_controller_->HasError());
158 // If there is an error we should see a notification.
159 const Notification* notification = notification_ui_manager_->FindById(
160 kNotificationId, NotificationUIManager::GetProfileID(profile_));
161 if (is_error) {
162 ASSERT_TRUE(notification);
163 ASSERT_FALSE(notification->title().empty());
164 ASSERT_FALSE(notification->title().empty());
165 ASSERT_EQ((size_t)1, notification->buttons().size());
166 } else {
167 ASSERT_FALSE(notification);
171 #if defined(OS_WIN)
172 scoped_ptr<gfx::Screen> test_screen_;
173 #endif
174 scoped_ptr<TestingProfileManager> profile_manager_;
175 scoped_ptr<SyncErrorController> error_controller_;
176 scoped_ptr<SyncErrorNotifier> error_notifier_;
177 scoped_ptr<NiceMock<ProfileSyncServiceMock> > service_;
178 TestingProfile* profile_;
179 FakeLoginUI login_ui_;
180 NotificationUIManager* notification_ui_manager_;
182 DISALLOW_COPY_AND_ASSIGN(SyncErrorNotifierTest);
185 } // namespace
187 // Test that SyncErrorNotifier shows an notification if a passphrase is
188 // required.
189 // Disabled on Windows: http://crbug.com/373238
190 #if defined(OS_WIN)
191 #define MAYBE_PassphraseNotification DISABLED_PassphraseNotification
192 #else
193 #define MAYBE_PassphraseNotification PassphraseNotification
194 #endif
195 TEST_F(SyncErrorNotifierTest, MAYBE_PassphraseNotification) {
196 ASSERT_FALSE(notification_ui_manager_->FindById(
197 kNotificationId, NotificationUIManager::GetProfileID(profile_)));
199 browser_sync::SyncBackendHost::Status status;
200 EXPECT_CALL(*service_, QueryDetailedSyncStatus(_))
201 .WillRepeatedly(Return(false));
203 EXPECT_CALL(*service_, IsPassphraseRequired())
204 .WillRepeatedly(Return(true));
205 EXPECT_CALL(*service_, IsPassphraseRequiredForDecryption())
206 .WillRepeatedly(Return(true));
208 SCOPED_TRACE("Expected a notification for passphrase error");
209 VerifySyncErrorNotifierResult(GoogleServiceAuthError::NONE,
210 true /* signed in */,
211 true /* error */);
214 // Check that no notification is shown if there is no error.
215 EXPECT_CALL(*service_, IsPassphraseRequired())
216 .WillRepeatedly(Return(false));
217 EXPECT_CALL(*service_, IsPassphraseRequiredForDecryption())
218 .WillRepeatedly(Return(false));
220 SCOPED_TRACE("Not expecting notification since no error exists");
221 VerifySyncErrorNotifierResult(GoogleServiceAuthError::NONE,
222 true /* signed in */,
223 false /* no error */);
226 // Check that no notification is shown if sync setup is not completed.
227 EXPECT_CALL(*service_, IsPassphraseRequired())
228 .WillRepeatedly(Return(true));
229 EXPECT_CALL(*service_, IsPassphraseRequiredForDecryption())
230 .WillRepeatedly(Return(true));
232 SCOPED_TRACE("Not expecting notification since sync setup is incomplete");
233 VerifySyncErrorNotifierResult(
234 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
235 false /* not signed in */,
236 false /* no error */);
240 } // namespace test
241 } // namespace ash