Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / glue / autofill_data_type_controller_unittest.cc
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/bind.h"
6 #include "base/callback.h"
7 #include "base/compiler_specific.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/run_loop.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/sync/glue/autofill_data_type_controller.h"
13 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
14 #include "chrome/browser/sync/profile_sync_service_factory.h"
15 #include "chrome/browser/sync/profile_sync_service_mock.h"
16 #include "chrome/browser/webdata/autocomplete_syncable_service.h"
17 #include "chrome/browser/webdata/web_data_service_factory.h"
18 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
19 #include "components/sync_driver/data_type_controller_mock.h"
20 #include "components/webdata/common/web_data_service_test_util.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/notification_source.h"
24 #include "content/public/browser/notification_types.h"
25 #include "content/public/test/test_browser_thread_bundle.h"
26 #include "sync/api/sync_error.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29
30 using autofill::AutofillWebDataService;
31 using autofill::AutofillWebDataBackend;
32
33 namespace browser_sync {
34
35 namespace {
36
37 using content::BrowserThread;
38 using testing::_;
39 using testing::Return;
40
41 class NoOpAutofillBackend : public AutofillWebDataBackend {
42  public:
43   NoOpAutofillBackend() {}
44   virtual ~NoOpAutofillBackend() {}
45   virtual WebDatabase* GetDatabase() OVERRIDE { return NULL; }
46   virtual void AddObserver(
47       autofill::AutofillWebDataServiceObserverOnDBThread* observer) OVERRIDE {}
48   virtual void RemoveObserver(
49       autofill::AutofillWebDataServiceObserverOnDBThread* observer) OVERRIDE {}
50   virtual void RemoveExpiredFormElements() OVERRIDE {}
51   virtual void NotifyOfMultipleAutofillChanges() OVERRIDE {}
52 };
53
54 // Fake WebDataService implementation that stubs out the database loading.
55 class FakeWebDataService : public AutofillWebDataService {
56  public:
57   FakeWebDataService()
58       : AutofillWebDataService(
59             BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
60             BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB)),
61         is_database_loaded_(false),
62         db_loaded_callback_(base::Callback<void(void)>()){}
63
64   // Mark the database as loaded and send out the appropriate notification.
65   void LoadDatabase() {
66     StartSyncableService();
67     is_database_loaded_ = true;
68
69     if (!db_loaded_callback_.is_null())
70       db_loaded_callback_.Run();
71   }
72
73   virtual bool IsDatabaseLoaded() OVERRIDE {
74     return is_database_loaded_;
75   }
76
77   virtual void RegisterDBLoadedCallback(
78       const base::Callback<void(void)>& callback) OVERRIDE {
79     db_loaded_callback_ = callback;
80   }
81
82   void StartSyncableService() {
83     // The |autofill_profile_syncable_service_| must be constructed on the DB
84     // thread.
85     base::RunLoop run_loop;
86     BrowserThread::PostTaskAndReply(BrowserThread::DB, FROM_HERE,
87         base::Bind(&FakeWebDataService::CreateSyncableService,
88                    base::Unretained(this)), run_loop.QuitClosure());
89     run_loop.Run();
90   }
91
92  private:
93   virtual ~FakeWebDataService() {
94   }
95
96   void CreateSyncableService() {
97     ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::DB));
98     // These services are deleted in DestroySyncableService().
99     AutocompleteSyncableService::CreateForWebDataServiceAndBackend(
100         this,
101         &autofill_backend_);
102   }
103
104   bool is_database_loaded_;
105   NoOpAutofillBackend autofill_backend_;
106   base::Callback<void(void)> db_loaded_callback_;
107
108   DISALLOW_COPY_AND_ASSIGN(FakeWebDataService);
109 };
110
111 class MockWebDataServiceWrapperSyncable : public MockWebDataServiceWrapper {
112  public:
113   static KeyedService* Build(content::BrowserContext* profile) {
114     return new MockWebDataServiceWrapperSyncable();
115   }
116
117   MockWebDataServiceWrapperSyncable()
118       : MockWebDataServiceWrapper(NULL, new FakeWebDataService(), NULL) {
119   }
120
121   virtual void Shutdown() OVERRIDE {
122     static_cast<FakeWebDataService*>(
123         fake_autofill_web_data_.get())->ShutdownOnUIThread();
124     // Make sure WebDataService is shutdown properly on DB thread before we
125     // destroy it.
126     base::RunLoop run_loop;
127     ASSERT_TRUE(BrowserThread::PostTaskAndReply(BrowserThread::DB, FROM_HERE,
128         base::Bind(&base::DoNothing), run_loop.QuitClosure()));
129     run_loop.Run();
130   }
131
132  private:
133   DISALLOW_COPY_AND_ASSIGN(MockWebDataServiceWrapperSyncable);
134 };
135
136 class SyncAutofillDataTypeControllerTest : public testing::Test {
137  public:
138   SyncAutofillDataTypeControllerTest()
139       : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD),
140         service_(&profile_),
141         last_start_result_(DataTypeController::OK),
142         weak_ptr_factory_(this) {}
143
144   virtual ~SyncAutofillDataTypeControllerTest() {}
145
146   virtual void SetUp() {
147     EXPECT_CALL(profile_sync_factory_,
148                 GetSyncableServiceForType(_)).
149         WillRepeatedly(Return(base::WeakPtr<syncer::SyncableService>()));
150
151     WebDataServiceFactory::GetInstance()->SetTestingFactory(
152         &profile_, MockWebDataServiceWrapperSyncable::Build);
153
154     autofill_dtc_ =
155         new AutofillDataTypeController(&profile_sync_factory_,
156                                        &profile_,
157                                        &service_);
158   }
159
160   // Passed to AutofillDTC::Start().
161   void OnStartFinished(DataTypeController::StartResult result,
162                        const syncer::SyncMergeResult& local_merge_result,
163                        const syncer::SyncMergeResult& syncer_merge_result) {
164     last_start_result_ = result;
165     last_start_error_ = local_merge_result.error();
166   }
167
168   void OnLoadFinished(syncer::ModelType type, syncer::SyncError error) {
169     EXPECT_FALSE(error.IsSet());
170     EXPECT_EQ(type, syncer::AUTOFILL);
171   }
172
173   virtual void TearDown() {
174     autofill_dtc_ = NULL;
175   }
176
177   void BlockForDBThread() {
178     base::RunLoop run_loop;
179     ASSERT_TRUE(BrowserThread::PostTaskAndReply(BrowserThread::DB, FROM_HERE,
180         base::Bind(&base::DoNothing), run_loop.QuitClosure()));
181     run_loop.Run();
182   }
183
184  protected:
185   content::TestBrowserThreadBundle thread_bundle_;
186   ProfileSyncComponentsFactoryMock profile_sync_factory_;
187   TestingProfile profile_;
188   ProfileSyncServiceMock service_;
189   scoped_refptr<AutofillDataTypeController> autofill_dtc_;
190
191   // Stores arguments of most recent call of OnStartFinished().
192   DataTypeController::StartResult last_start_result_;
193   syncer::SyncError last_start_error_;
194   base::WeakPtrFactory<SyncAutofillDataTypeControllerTest> weak_ptr_factory_;
195 };
196
197 // Load the WDS's database, then start the Autofill DTC.  It should
198 // immediately try to start association and fail (due to missing DB
199 // thread).
200 TEST_F(SyncAutofillDataTypeControllerTest, StartWDSReady) {
201   FakeWebDataService* web_db =
202       static_cast<FakeWebDataService*>(
203           WebDataServiceFactory::GetAutofillWebDataForProfile(
204               &profile_, Profile::EXPLICIT_ACCESS).get());
205   web_db->LoadDatabase();
206   autofill_dtc_->LoadModels(
207     base::Bind(&SyncAutofillDataTypeControllerTest::OnLoadFinished,
208                weak_ptr_factory_.GetWeakPtr()));
209
210   autofill_dtc_->StartAssociating(
211       base::Bind(&SyncAutofillDataTypeControllerTest::OnStartFinished,
212                  weak_ptr_factory_.GetWeakPtr()));
213   BlockForDBThread();
214
215   EXPECT_EQ(DataTypeController::ASSOCIATION_FAILED, last_start_result_);
216   EXPECT_TRUE(last_start_error_.IsSet());
217   EXPECT_EQ(DataTypeController::DISABLED, autofill_dtc_->state());
218 }
219
220 // Start the autofill DTC without the WDS's database loaded, then
221 // start the DB.  The Autofill DTC should be in the MODEL_STARTING
222 // state until the database in loaded, when it should try to start
223 // association and fail (due to missing DB thread).
224 TEST_F(SyncAutofillDataTypeControllerTest, StartWDSNotReady) {
225   autofill_dtc_->LoadModels(
226     base::Bind(&SyncAutofillDataTypeControllerTest::OnLoadFinished,
227                weak_ptr_factory_.GetWeakPtr()));
228
229   EXPECT_EQ(DataTypeController::OK, last_start_result_);
230   EXPECT_FALSE(last_start_error_.IsSet());
231   EXPECT_EQ(DataTypeController::MODEL_STARTING, autofill_dtc_->state());
232
233   FakeWebDataService* web_db =
234       static_cast<FakeWebDataService*>(
235           WebDataServiceFactory::GetAutofillWebDataForProfile(
236               &profile_, Profile::EXPLICIT_ACCESS).get());
237   web_db->LoadDatabase();
238
239   autofill_dtc_->StartAssociating(
240       base::Bind(&SyncAutofillDataTypeControllerTest::OnStartFinished,
241                  weak_ptr_factory_.GetWeakPtr()));
242   BlockForDBThread();
243
244   EXPECT_EQ(DataTypeController::ASSOCIATION_FAILED, last_start_result_);
245   EXPECT_TRUE(last_start_error_.IsSet());
246
247   EXPECT_EQ(DataTypeController::DISABLED, autofill_dtc_->state());
248 }
249
250 }  // namespace
251
252 }  // namespace browser_sync