• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/basictypes.h"
6 #include "base/compiler_specific.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/run_loop.h"
9 #include "base/values.h"
10 #include "chrome/browser/invalidation/invalidation_service_factory.h"
11 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
12 #include "chrome/browser/signin/signin_manager.h"
13 #include "chrome/browser/signin/signin_manager_factory.h"
14 #include "chrome/browser/sync/fake_oauth2_token_service.h"
15 #include "chrome/browser/sync/glue/data_type_manager_impl.h"
16 #include "chrome/browser/sync/glue/sync_backend_host_mock.h"
17 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
18 #include "chrome/common/pref_names.h"
19 #include "chrome/test/base/testing_pref_service_syncable.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "google_apis/gaia/gaia_constants.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 
26 namespace browser_sync {
27 
28 namespace {
29 
ACTION(ReturnNewDataTypeManager)30 ACTION(ReturnNewDataTypeManager) {
31   return new browser_sync::DataTypeManagerImpl(arg0,
32                                                arg1,
33                                                arg2,
34                                                arg3,
35                                                arg4,
36                                                arg5);
37 }
38 
39 using testing::_;
40 using testing::StrictMock;
41 
42 class TestProfileSyncServiceObserver : public ProfileSyncServiceObserver {
43  public:
TestProfileSyncServiceObserver(ProfileSyncService * service)44   explicit TestProfileSyncServiceObserver(ProfileSyncService* service)
45       : service_(service), first_setup_in_progress_(false) {}
OnStateChanged()46   virtual void OnStateChanged() OVERRIDE {
47     first_setup_in_progress_ = service_->FirstSetupInProgress();
48   }
first_setup_in_progress() const49   bool first_setup_in_progress() const { return first_setup_in_progress_; }
50  private:
51   ProfileSyncService* service_;
52   bool first_setup_in_progress_;
53 };
54 
55 // A variant of the SyncBackendHostMock that won't automatically
56 // call back when asked to initialized.  Allows us to test things
57 // that could happen while backend init is in progress.
58 class SyncBackendHostNoReturn : public SyncBackendHostMock {
Initialize(SyncFrontend * frontend,scoped_ptr<base::Thread> sync_thread,const syncer::WeakHandle<syncer::JsEventHandler> & event_handler,const GURL & service_url,const syncer::SyncCredentials & credentials,bool delete_sync_data_folder,scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,syncer::ReportUnrecoverableErrorFunction report_unrecoverable_error_function,syncer::NetworkResources * network_resources)59   virtual void Initialize(
60       SyncFrontend* frontend,
61       scoped_ptr<base::Thread> sync_thread,
62       const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
63       const GURL& service_url,
64       const syncer::SyncCredentials& credentials,
65       bool delete_sync_data_folder,
66       scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
67       scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
68       syncer::ReportUnrecoverableErrorFunction
69           report_unrecoverable_error_function,
70       syncer::NetworkResources* network_resources) OVERRIDE {}
71 };
72 
ACTION(ReturnNewSyncBackendHostMock)73 ACTION(ReturnNewSyncBackendHostMock) {
74   return new browser_sync::SyncBackendHostMock();
75 }
76 
ACTION(ReturnNewSyncBackendHostNoReturn)77 ACTION(ReturnNewSyncBackendHostNoReturn) {
78   return new browser_sync::SyncBackendHostNoReturn();
79 }
80 
81 // A test harness that uses a real ProfileSyncService and in most cases a
82 // MockSyncBackendHost.
83 //
84 // This is useful if we want to test the ProfileSyncService and don't care about
85 // testing the SyncBackendHost.
86 class ProfileSyncServiceTest : public ::testing::Test {
87  protected:
ProfileSyncServiceTest()88   ProfileSyncServiceTest()
89       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
~ProfileSyncServiceTest()90   virtual ~ProfileSyncServiceTest() {}
91 
SetUp()92   virtual void SetUp() OVERRIDE {
93     TestingProfile::Builder builder;
94 
95     builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
96                               FakeOAuth2TokenService::BuildTokenService);
97     invalidation::InvalidationServiceFactory::GetInstance()->
98         SetBuildOnlyFakeInvalidatorsForTest(true);
99 
100     profile_ = builder.Build().Pass();
101   }
102 
TearDown()103   virtual void TearDown() OVERRIDE {
104     // Kill the service before the profile.
105     if (service_)
106       service_->Shutdown();
107 
108     service_.reset();
109     profile_.reset();
110   }
111 
IssueTestTokens()112   void IssueTestTokens() {
113     ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())
114         ->UpdateCredentials("test", "oauth2_login_token");
115   }
116 
CreateService(ProfileSyncService::StartBehavior behavior)117   void CreateService(ProfileSyncService::StartBehavior behavior) {
118     SigninManagerBase* signin =
119         SigninManagerFactory::GetForProfile(profile_.get());
120     signin->SetAuthenticatedUsername("test");
121     ProfileOAuth2TokenService* oauth2_token_service =
122         ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
123     components_factory_ = new StrictMock<ProfileSyncComponentsFactoryMock>();
124     service_.reset(new ProfileSyncService(
125         components_factory_,
126         profile_.get(),
127         signin,
128         oauth2_token_service,
129         behavior));
130   }
131 
ShutdownAndDeleteService()132   void ShutdownAndDeleteService() {
133     if (service_)
134       service_->Shutdown();
135     service_.reset();
136   }
137 
Initialize()138   void Initialize() {
139     service_->Initialize();
140   }
141 
ExpectDataTypeManagerCreation()142   void ExpectDataTypeManagerCreation() {
143     EXPECT_CALL(*components_factory_, CreateDataTypeManager(_, _, _, _, _, _)).
144         WillOnce(ReturnNewDataTypeManager());
145   }
146 
ExpectSyncBackendHostCreation()147   void ExpectSyncBackendHostCreation() {
148     EXPECT_CALL(*components_factory_, CreateSyncBackendHost(_, _, _)).
149         WillOnce(ReturnNewSyncBackendHostMock());
150   }
151 
PrepareDelayedInitSyncBackendHost()152   void PrepareDelayedInitSyncBackendHost() {
153     EXPECT_CALL(*components_factory_, CreateSyncBackendHost(_, _, _)).
154         WillOnce(ReturnNewSyncBackendHostNoReturn());
155   }
156 
profile()157   TestingProfile* profile() {
158     return profile_.get();
159   }
160 
service()161   ProfileSyncService* service() {
162     return service_.get();
163   }
164 
components_factory()165   ProfileSyncComponentsFactoryMock* components_factory() {
166     return components_factory_;
167   }
168 
169  private:
170   scoped_ptr<TestingProfile> profile_;
171   scoped_ptr<ProfileSyncService> service_;
172 
173   // Pointer to the components factory.  Not owned.  May be null.
174   ProfileSyncComponentsFactoryMock* components_factory_;
175 
176   content::TestBrowserThreadBundle thread_bundle_;
177 };
178 
179 // Verify that the server URLs are sane.
TEST_F(ProfileSyncServiceTest,InitialState)180 TEST_F(ProfileSyncServiceTest, InitialState) {
181   CreateService(ProfileSyncService::AUTO_START);
182   Initialize();
183   const std::string& url = service()->sync_service_url().spec();
184   EXPECT_TRUE(url == ProfileSyncService::kSyncServerUrl ||
185               url == ProfileSyncService::kDevServerUrl);
186 }
187 
188 // Verify a successful initialization.
TEST_F(ProfileSyncServiceTest,SuccessfulInitialization)189 TEST_F(ProfileSyncServiceTest, SuccessfulInitialization) {
190   profile()->GetTestingPrefService()->SetManagedPref(
191       prefs::kSyncManaged,
192       Value::CreateBooleanValue(false));
193   IssueTestTokens();
194   CreateService(ProfileSyncService::AUTO_START);
195   ExpectDataTypeManagerCreation();
196   ExpectSyncBackendHostCreation();
197   Initialize();
198   EXPECT_FALSE(service()->IsManaged());
199   EXPECT_TRUE(service()->sync_initialized());
200 }
201 
202 
203 // Verify that the SetSetupInProgress function call updates state
204 // and notifies observers.
TEST_F(ProfileSyncServiceTest,SetupInProgress)205 TEST_F(ProfileSyncServiceTest, SetupInProgress) {
206   CreateService(ProfileSyncService::MANUAL_START);
207   Initialize();
208 
209   TestProfileSyncServiceObserver observer(service());
210   service()->AddObserver(&observer);
211 
212   service()->SetSetupInProgress(true);
213   EXPECT_TRUE(observer.first_setup_in_progress());
214   service()->SetSetupInProgress(false);
215   EXPECT_FALSE(observer.first_setup_in_progress());
216 
217   service()->RemoveObserver(&observer);
218 }
219 
220 // Verify that disable by enterprise policy works.
TEST_F(ProfileSyncServiceTest,DisabledByPolicyBeforeInit)221 TEST_F(ProfileSyncServiceTest, DisabledByPolicyBeforeInit) {
222   profile()->GetTestingPrefService()->SetManagedPref(
223       prefs::kSyncManaged,
224       Value::CreateBooleanValue(true));
225   IssueTestTokens();
226   CreateService(ProfileSyncService::AUTO_START);
227   Initialize();
228   EXPECT_TRUE(service()->IsManaged());
229   EXPECT_FALSE(service()->sync_initialized());
230 }
231 
232 // Verify that disable by enterprise policy works even after the backend has
233 // been initialized.
TEST_F(ProfileSyncServiceTest,DisabledByPolicyAfterInit)234 TEST_F(ProfileSyncServiceTest, DisabledByPolicyAfterInit) {
235   IssueTestTokens();
236   CreateService(ProfileSyncService::AUTO_START);
237   ExpectDataTypeManagerCreation();
238   ExpectSyncBackendHostCreation();
239   Initialize();
240 
241   EXPECT_FALSE(service()->IsManaged());
242   EXPECT_TRUE(service()->sync_initialized());
243 
244   profile()->GetTestingPrefService()->SetManagedPref(
245       prefs::kSyncManaged,
246       Value::CreateBooleanValue(true));
247 
248   EXPECT_TRUE(service()->IsManaged());
249   EXPECT_FALSE(service()->sync_initialized());
250 }
251 
252 // Exercies the ProfileSyncService's code paths related to getting shut down
253 // before the backend initialize call returns.
TEST_F(ProfileSyncServiceTest,AbortedByShutdown)254 TEST_F(ProfileSyncServiceTest, AbortedByShutdown) {
255   CreateService(ProfileSyncService::AUTO_START);
256   PrepareDelayedInitSyncBackendHost();
257 
258   IssueTestTokens();
259   Initialize();
260   EXPECT_FALSE(service()->sync_initialized());
261 
262   ShutdownAndDeleteService();
263 }
264 
265 // Test StopAndSuppress() before we've initialized the backend.
TEST_F(ProfileSyncServiceTest,EarlyStopAndSuppress)266 TEST_F(ProfileSyncServiceTest, EarlyStopAndSuppress) {
267   CreateService(ProfileSyncService::AUTO_START);
268   IssueTestTokens();
269 
270   service()->StopAndSuppress();
271   EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
272 
273   // Because of supression, this should fail.
274   Initialize();
275   EXPECT_FALSE(service()->sync_initialized());
276 
277   // Remove suppression.  This should be enough to allow init to happen.
278   ExpectDataTypeManagerCreation();
279   ExpectSyncBackendHostCreation();
280   service()->UnsuppressAndStart();
281   EXPECT_TRUE(service()->sync_initialized());
282   EXPECT_FALSE(
283       profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
284 }
285 
286 // Test StopAndSuppress() after we've initialized the backend.
TEST_F(ProfileSyncServiceTest,DisableAndEnableSyncTemporarily)287 TEST_F(ProfileSyncServiceTest, DisableAndEnableSyncTemporarily) {
288   CreateService(ProfileSyncService::AUTO_START);
289   IssueTestTokens();
290   ExpectDataTypeManagerCreation();
291   ExpectSyncBackendHostCreation();
292   Initialize();
293 
294   EXPECT_TRUE(service()->sync_initialized());
295   EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
296 
297   testing::Mock::VerifyAndClearExpectations(components_factory());
298 
299   service()->StopAndSuppress();
300   EXPECT_FALSE(service()->sync_initialized());
301   EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
302 
303   ExpectDataTypeManagerCreation();
304   ExpectSyncBackendHostCreation();
305 
306   service()->UnsuppressAndStart();
307   EXPECT_TRUE(service()->sync_initialized());
308   EXPECT_FALSE(
309       profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
310 }
311 
312 // Certain ProfileSyncService tests don't apply to Chrome OS, for example
313 // things that deal with concepts like "signing out" and policy.
314 #if !defined (OS_CHROMEOS)
315 
TEST_F(ProfileSyncServiceTest,EnableSyncAndSignOut)316 TEST_F(ProfileSyncServiceTest, EnableSyncAndSignOut) {
317   CreateService(ProfileSyncService::AUTO_START);
318   ExpectDataTypeManagerCreation();
319   ExpectSyncBackendHostCreation();
320   IssueTestTokens();
321   Initialize();
322 
323   EXPECT_TRUE(service()->sync_initialized());
324   EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
325 
326   SigninManagerFactory::GetForProfile(profile())->SignOut();
327   EXPECT_FALSE(service()->sync_initialized());
328 }
329 
330 #endif  // !defined(OS_CHROMEOS)
331 
TEST_F(ProfileSyncServiceTest,GetSyncTokenStatus)332 TEST_F(ProfileSyncServiceTest, GetSyncTokenStatus) {
333   CreateService(ProfileSyncService::AUTO_START);
334   IssueTestTokens();
335   ExpectDataTypeManagerCreation();
336   ExpectSyncBackendHostCreation();
337   Initialize();
338 
339   // Initial status.
340   ProfileSyncService::SyncTokenStatus token_status =
341       service()->GetSyncTokenStatus();
342   EXPECT_EQ(syncer::CONNECTION_NOT_ATTEMPTED, token_status.connection_status);
343   EXPECT_TRUE(token_status.connection_status_update_time.is_null());
344   EXPECT_TRUE(token_status.token_request_time.is_null());
345   EXPECT_TRUE(token_status.token_receive_time.is_null());
346 
347   // Simulate an auth error.
348   service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);
349 
350   // The token request will take the form of a posted task.  Run it.
351   base::RunLoop loop;
352   loop.RunUntilIdle();
353 
354   token_status = service()->GetSyncTokenStatus();
355   EXPECT_EQ(syncer::CONNECTION_AUTH_ERROR, token_status.connection_status);
356   EXPECT_FALSE(token_status.connection_status_update_time.is_null());
357   EXPECT_FALSE(token_status.token_request_time.is_null());
358   EXPECT_FALSE(token_status.token_receive_time.is_null());
359   EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
360             token_status.last_get_token_error);
361   EXPECT_TRUE(token_status.next_token_request_time.is_null());
362 
363   // Simulate successful connection.
364   service()->OnConnectionStatusChange(syncer::CONNECTION_OK);
365   token_status = service()->GetSyncTokenStatus();
366   EXPECT_EQ(syncer::CONNECTION_OK, token_status.connection_status);
367 }
368 
369 }  // namespace
370 }  // namespace browser_sync
371