1 // Copyright (c) 2012 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/sync/sync_global_error.h" 6 7 #include "base/basictypes.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "chrome/app/chrome_command_ids.h" 10 #include "chrome/browser/signin/signin_manager.h" 11 #include "chrome/browser/signin/signin_manager_factory.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/browser_with_test_window_test.h" 17 #include "chrome/test/base/testing_profile.h" 18 #include "content/public/test/test_browser_thread.h" 19 #include "testing/gmock/include/gmock/gmock-actions.h" 20 #include "testing/gmock/include/gmock/gmock.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 23 using ::testing::NiceMock; 24 using ::testing::Return; 25 using ::testing::ReturnRef; 26 using ::testing::_; 27 using content::BrowserThread; 28 29 namespace { 30 31 #if 0 32 // TODO(altimofeev) See below. 33 class BrowserMock: public Browser { 34 public: 35 explicit BrowserMock(Type type, Profile* profile) : Browser(type, profile) {} 36 37 MOCK_METHOD2(ExecuteCommandWithDisposition, 38 void(int command_id, WindowOpenDisposition)); 39 }; 40 #endif 41 42 class FakeLoginUIService: public LoginUIService { 43 public: 44 FakeLoginUIService() : LoginUIService(NULL) {} 45 }; 46 47 class FakeLoginUI : public LoginUIService::LoginUI { 48 public: 49 FakeLoginUI() : focus_ui_call_count_(0) {} 50 51 virtual ~FakeLoginUI() {} 52 53 int focus_ui_call_count() const { return focus_ui_call_count_; } 54 55 private: 56 // Overridden from LoginUIService::LoginUI: 57 virtual void FocusUI() OVERRIDE { 58 ++focus_ui_call_count_; 59 } 60 virtual void CloseUI() OVERRIDE {} 61 62 int focus_ui_call_count_; 63 }; 64 65 BrowserContextKeyedService* BuildMockLoginUIService( 66 content::BrowserContext* profile) { 67 return new FakeLoginUIService(); 68 } 69 70 // Same as BrowserWithTestWindowTest, but uses MockBrowser to test calls to 71 // ExecuteCommand method. 72 class SyncGlobalErrorTest : public BrowserWithTestWindowTest { 73 public: 74 SyncGlobalErrorTest() {} 75 virtual ~SyncGlobalErrorTest() {} 76 77 #if 0 78 // TODO(altimofeev): see below. 79 virtual void SetUp() OVERRIDE { 80 testing::Test::SetUp(); 81 82 set_profile(CreateProfile()); 83 set_browser(new BrowserMock(Browser::TYPE_TABBED, profile())); 84 set_window(new TestBrowserWindow(browser())); 85 browser()->SetWindowForTesting(window()); 86 } 87 88 virtual void TearDown() OVERRIDE { 89 testing::Test::TearDown(); 90 } 91 #endif 92 93 private: 94 DISALLOW_COPY_AND_ASSIGN(SyncGlobalErrorTest); 95 }; 96 97 // Utility function to test that SyncGlobalError behaves correct for the given 98 // error condition. 99 void VerifySyncGlobalErrorResult(NiceMock<ProfileSyncServiceMock>* service, 100 FakeLoginUIService* login_ui_service, 101 Browser* browser, 102 SyncGlobalError* error, 103 GoogleServiceAuthError::State error_state, 104 bool is_signed_in, 105 bool is_error) { 106 EXPECT_CALL(*service, HasSyncSetupCompleted()) 107 .WillRepeatedly(Return(is_signed_in)); 108 109 GoogleServiceAuthError auth_error(error_state); 110 EXPECT_CALL(*service, GetAuthError()).WillRepeatedly(ReturnRef(auth_error)); 111 112 error->OnStateChanged(); 113 114 // If there is an error then a menu item and bubble view should be shown. 115 EXPECT_EQ(error->HasMenuItem(), is_error); 116 EXPECT_EQ(error->HasBubbleView(), is_error); 117 118 // If there is an error then labels should not be empty. 119 EXPECT_NE(error->MenuItemCommandID(), 0); 120 EXPECT_NE(error->MenuItemLabel().empty(), is_error); 121 EXPECT_NE(error->GetBubbleViewAcceptButtonLabel().empty(), is_error); 122 123 // We never have a cancel button. 124 EXPECT_TRUE(error->GetBubbleViewCancelButtonLabel().empty()); 125 // We always return a hardcoded title. 126 EXPECT_FALSE(error->GetBubbleViewTitle().empty()); 127 128 #if defined(OS_CHROMEOS) 129 // TODO(altimofeev): Implement this in a way that doesn't involve subclassing 130 // Browser or using GMock on browser/ui types which is 131 // banned. Consider observing NOTIFICATION_APP_TERMINATING 132 // instead. 133 // http://crbug.com/134675 134 #else 135 #if defined(OS_CHROMEOS) 136 if (error_state != GoogleServiceAuthError::NONE) { 137 // In CrOS sign-in/sign-out is made to fix the error. 138 EXPECT_CALL(*static_cast<BrowserMock*>(browser), 139 ExecuteCommandWithDisposition(IDC_EXIT, _)); 140 error->ExecuteMenuItem(browser); 141 } 142 #else 143 // Test message handler. 144 if (is_error) { 145 FakeLoginUI* login_ui = static_cast<FakeLoginUI*>( 146 login_ui_service->current_login_ui()); 147 error->ExecuteMenuItem(browser); 148 ASSERT_GT(login_ui->focus_ui_call_count(), 0); 149 error->BubbleViewAcceptButtonPressed(browser); 150 error->BubbleViewDidClose(browser); 151 } 152 #endif 153 #endif 154 } 155 156 } // namespace 157 158 // Test that SyncGlobalError shows an error if a passphrase is required. 159 TEST_F(SyncGlobalErrorTest, PassphraseGlobalError) { 160 scoped_ptr<Profile> profile( 161 ProfileSyncServiceMock::MakeSignedInTestingProfile()); 162 NiceMock<ProfileSyncServiceMock> service(profile.get()); 163 SigninManagerBase* signin = 164 SigninManagerFactory::GetForProfile(profile.get()); 165 FakeLoginUIService* login_ui_service = static_cast<FakeLoginUIService*>( 166 LoginUIServiceFactory::GetInstance()->SetTestingFactoryAndUse( 167 profile.get(), BuildMockLoginUIService)); 168 FakeLoginUI login_ui; 169 login_ui_service->SetLoginUI(&login_ui); 170 SyncGlobalError error(&service, signin); 171 172 browser_sync::SyncBackendHost::Status status; 173 EXPECT_CALL(service, QueryDetailedSyncStatus(_)) 174 .WillRepeatedly(Return(false)); 175 176 EXPECT_CALL(service, IsPassphraseRequired()) 177 .WillRepeatedly(Return(true)); 178 EXPECT_CALL(service, IsPassphraseRequiredForDecryption()) 179 .WillRepeatedly(Return(true)); 180 VerifySyncGlobalErrorResult( 181 &service, login_ui_service, browser(), &error, 182 GoogleServiceAuthError::NONE, true, true); 183 } 184