Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / test / integration / passwords_helper.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 "chrome/browser/sync/test/integration/passwords_helper.h"
6
7 #include "base/compiler_specific.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/time/time.h"
12 #include "chrome/browser/password_manager/password_store_factory.h"
13 #include "chrome/browser/sync/profile_sync_service.h"
14 #include "chrome/browser/sync/profile_sync_service_factory.h"
15 #include "chrome/browser/sync/test/integration/multi_client_status_change_checker.h"
16 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
17 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
18 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "components/password_manager/core/browser/password_form_data.h"
21 #include "components/password_manager/core/browser/password_store.h"
22 #include "components/password_manager/core/browser/password_store_consumer.h"
23
24 using autofill::PasswordForm;
25 using password_manager::PasswordStore;
26 using sync_datatype_helper::test;
27
28 const std::string kFakeSignonRealm = "http://fake-signon-realm.google.com/";
29 const char* kIndexedFakeOrigin = "http://fake-signon-realm.google.com/%d";
30
31 namespace {
32
33 // We use a WaitableEvent to wait when logins are added, removed, or updated
34 // instead of running the UI message loop because of a restriction that
35 // prevents a DB thread from initiating a quit of the UI message loop.
36 void PasswordStoreCallback(base::WaitableEvent* wait_event) {
37   // Wake up passwords_helper::AddLogin.
38   wait_event->Signal();
39 }
40
41 class PasswordStoreConsumerHelper
42     : public password_manager::PasswordStoreConsumer {
43  public:
44   explicit PasswordStoreConsumerHelper(std::vector<PasswordForm>* result)
45       : password_manager::PasswordStoreConsumer(), result_(result) {}
46
47   virtual void OnGetPasswordStoreResults(
48       const std::vector<PasswordForm*>& result) OVERRIDE {
49     result_->clear();
50     for (std::vector<PasswordForm*>::const_iterator it = result.begin();
51          it != result.end();
52          ++it) {
53       result_->push_back(**it);
54       delete *it;
55     }
56
57     // Quit the message loop to wake up passwords_helper::GetLogins.
58     base::MessageLoopForUI::current()->Quit();
59   }
60
61  private:
62   std::vector<PasswordForm>* result_;
63
64   DISALLOW_COPY_AND_ASSIGN(PasswordStoreConsumerHelper);
65 };
66
67 }  // namespace
68
69 namespace passwords_helper {
70
71 void AddLogin(PasswordStore* store, const PasswordForm& form) {
72   ASSERT_TRUE(store);
73   base::WaitableEvent wait_event(true, false);
74   store->AddLogin(form);
75   store->ScheduleTask(base::Bind(&PasswordStoreCallback, &wait_event));
76   wait_event.Wait();
77 }
78
79 void UpdateLogin(PasswordStore* store, const PasswordForm& form) {
80   ASSERT_TRUE(store);
81   base::WaitableEvent wait_event(true, false);
82   store->UpdateLogin(form);
83   store->ScheduleTask(base::Bind(&PasswordStoreCallback, &wait_event));
84   wait_event.Wait();
85 }
86
87 void GetLogins(PasswordStore* store, std::vector<PasswordForm>& matches) {
88   ASSERT_TRUE(store);
89   PasswordForm matcher_form;
90   matcher_form.signon_realm = kFakeSignonRealm;
91   PasswordStoreConsumerHelper consumer(&matches);
92   store->GetLogins(matcher_form, PasswordStore::DISALLOW_PROMPT, &consumer);
93   content::RunMessageLoop();
94 }
95
96 void RemoveLogin(PasswordStore* store, const PasswordForm& form) {
97   ASSERT_TRUE(store);
98   base::WaitableEvent wait_event(true, false);
99   store->RemoveLogin(form);
100   store->ScheduleTask(base::Bind(&PasswordStoreCallback, &wait_event));
101   wait_event.Wait();
102 }
103
104 void RemoveLogins(PasswordStore* store) {
105   std::vector<PasswordForm> forms;
106   GetLogins(store, forms);
107   for (std::vector<PasswordForm>::iterator it = forms.begin();
108        it != forms.end(); ++it) {
109     RemoveLogin(store, *it);
110   }
111 }
112
113 void SetEncryptionPassphrase(int index,
114                              const std::string& passphrase,
115                              ProfileSyncService::PassphraseType type) {
116   ProfileSyncServiceFactory::GetForProfile(
117       test()->GetProfile(index))->SetEncryptionPassphrase(passphrase, type);
118 }
119
120 bool SetDecryptionPassphrase(int index, const std::string& passphrase) {
121   return ProfileSyncServiceFactory::GetForProfile(
122       test()->GetProfile(index))->SetDecryptionPassphrase(passphrase);
123 }
124
125 PasswordStore* GetPasswordStore(int index) {
126   return PasswordStoreFactory::GetForProfile(test()->GetProfile(index),
127                                              Profile::IMPLICIT_ACCESS).get();
128 }
129
130 PasswordStore* GetVerifierPasswordStore() {
131   return PasswordStoreFactory::GetForProfile(test()->verifier(),
132                                              Profile::IMPLICIT_ACCESS).get();
133 }
134
135 bool ProfileContainsSamePasswordFormsAsVerifier(int index) {
136   std::vector<PasswordForm> verifier_forms;
137   std::vector<PasswordForm> forms;
138   GetLogins(GetVerifierPasswordStore(), verifier_forms);
139   GetLogins(GetPasswordStore(index), forms);
140   bool result =
141       password_manager::ContainsSamePasswordForms(verifier_forms, forms);
142   if (!result) {
143     LOG(ERROR) << "Password forms in Verifier Profile:";
144     for (std::vector<PasswordForm>::iterator it = verifier_forms.begin();
145          it != verifier_forms.end(); ++it) {
146       LOG(ERROR) << *it << std::endl;
147     }
148     LOG(ERROR) << "Password forms in Profile" << index << ":";
149     for (std::vector<PasswordForm>::iterator it = forms.begin();
150          it != forms.end(); ++it) {
151       LOG(ERROR) << *it << std::endl;
152     }
153   }
154   return result;
155 }
156
157 bool ProfilesContainSamePasswordForms(int index_a, int index_b) {
158   std::vector<PasswordForm> forms_a;
159   std::vector<PasswordForm> forms_b;
160   GetLogins(GetPasswordStore(index_a), forms_a);
161   GetLogins(GetPasswordStore(index_b), forms_b);
162   bool result = password_manager::ContainsSamePasswordForms(forms_a, forms_b);
163   if (!result) {
164     LOG(ERROR) << "Password forms in Profile" << index_a << ":";
165     for (std::vector<PasswordForm>::iterator it = forms_a.begin();
166          it != forms_a.end(); ++it) {
167       LOG(ERROR) << *it << std::endl;
168     }
169     LOG(ERROR) << "Password forms in Profile" << index_b << ":";
170     for (std::vector<PasswordForm>::iterator it = forms_b.begin();
171          it != forms_b.end(); ++it) {
172       LOG(ERROR) << *it << std::endl;
173     }
174   }
175   return result;
176 }
177
178 bool AllProfilesContainSamePasswordFormsAsVerifier() {
179   for (int i = 0; i < test()->num_clients(); ++i) {
180     if (!ProfileContainsSamePasswordFormsAsVerifier(i)) {
181       DVLOG(1) << "Profile " << i << " does not contain the same password"
182                                      " forms as the verifier.";
183       return false;
184     }
185   }
186   return true;
187 }
188
189 bool AllProfilesContainSamePasswordForms() {
190   for (int i = 1; i < test()->num_clients(); ++i) {
191     if (!ProfilesContainSamePasswordForms(0, i)) {
192       DVLOG(1) << "Profile " << i << " does not contain the same password"
193                                      " forms as Profile 0.";
194       return false;
195     }
196   }
197   return true;
198 }
199
200 namespace {
201
202 // Helper class used in the implementation of
203 // AwaitAllProfilesContainSamePasswordForms.
204 class SamePasswordFormsChecker : public MultiClientStatusChangeChecker {
205  public:
206   SamePasswordFormsChecker();
207   virtual ~SamePasswordFormsChecker();
208
209   virtual bool IsExitConditionSatisfied() OVERRIDE;
210   virtual std::string GetDebugMessage() const OVERRIDE;
211
212  private:
213   bool in_progress_;
214   bool needs_recheck_;
215 };
216
217 SamePasswordFormsChecker::SamePasswordFormsChecker()
218     : MultiClientStatusChangeChecker(
219         sync_datatype_helper::test()->GetSyncServices()),
220       in_progress_(false),
221       needs_recheck_(false) {}
222
223 SamePasswordFormsChecker::~SamePasswordFormsChecker() {}
224
225 // This method needs protection against re-entrancy.
226 //
227 // This function indirectly calls GetLogins(), which starts a RunLoop on the UI
228 // thread.  This can be a problem, since the next task to execute could very
229 // well contain a ProfileSyncService::OnStateChanged() event, which would
230 // trigger another call to this here function, and start another layer of
231 // nested RunLoops.  That makes the StatusChangeChecker's Quit() method
232 // ineffective.
233 //
234 // The work-around is to not allow re-entrancy.  But we can't just drop
235 // IsExitConditionSatisifed() calls if one is already in progress.  Instead, we
236 // set a flag to ask the current execution of IsExitConditionSatisfied() to be
237 // re-run.  This ensures that the return value is always based on the most
238 // up-to-date state.
239 bool SamePasswordFormsChecker::IsExitConditionSatisfied() {
240   if (in_progress_) {
241     LOG(WARNING) << "Setting flag and returning early to prevent nesting.";
242     needs_recheck_ = true;
243     return false;
244   }
245
246   // Keep retrying until we get a good reading.
247   bool result = false;
248   in_progress_ = true;
249   do {
250     needs_recheck_ = false;
251     result = AllProfilesContainSamePasswordForms();
252   } while (needs_recheck_);
253   in_progress_ = false;
254   return result;
255 }
256
257 std::string SamePasswordFormsChecker::GetDebugMessage() const {
258   return "Waiting for matching passwords";
259 }
260
261 }  //  namespace
262
263 bool AwaitAllProfilesContainSamePasswordForms() {
264   SamePasswordFormsChecker checker;
265   checker.Wait();
266   return !checker.TimedOut();
267 }
268
269 namespace {
270
271 // Helper class used in the implementation of
272 // AwaitProfileContainSamePasswordFormsAsVerifier.
273 class SamePasswordFormsAsVerifierChecker
274     : public SingleClientStatusChangeChecker {
275  public:
276   explicit SamePasswordFormsAsVerifierChecker(int index);
277   virtual ~SamePasswordFormsAsVerifierChecker();
278
279   virtual bool IsExitConditionSatisfied() OVERRIDE;
280   virtual std::string GetDebugMessage() const OVERRIDE;
281
282  private:
283   int index_;
284
285   bool in_progress_;
286   bool needs_recheck_;
287 };
288
289 SamePasswordFormsAsVerifierChecker::SamePasswordFormsAsVerifierChecker(int i)
290     : SingleClientStatusChangeChecker(
291           sync_datatype_helper::test()->GetSyncService(i)),
292       index_(i),
293       in_progress_(false),
294       needs_recheck_(false) {
295 }
296
297 SamePasswordFormsAsVerifierChecker::~SamePasswordFormsAsVerifierChecker() {
298 }
299
300 // This method uses the same re-entrancy prevention trick as
301 // the SamePasswordFormsChecker.
302 bool SamePasswordFormsAsVerifierChecker::IsExitConditionSatisfied() {
303   if (in_progress_) {
304     LOG(WARNING) << "Setting flag and returning early to prevent nesting.";
305     needs_recheck_ = true;
306     return false;
307   }
308
309   // Keep retrying until we get a good reading.
310   bool result = false;
311   in_progress_ = true;
312   do {
313     needs_recheck_ = false;
314     result = ProfileContainsSamePasswordFormsAsVerifier(index_);
315   } while (needs_recheck_);
316   in_progress_ = false;
317   return result;
318 }
319
320 std::string SamePasswordFormsAsVerifierChecker::GetDebugMessage() const {
321   return "Waiting for passwords to match verifier";
322 }
323
324 }  //  namespace
325
326 bool AwaitProfileContainsSamePasswordFormsAsVerifier(int index) {
327   SamePasswordFormsAsVerifierChecker checker(index);
328   checker.Wait();
329   return !checker.TimedOut();
330 }
331
332 int GetPasswordCount(int index) {
333   std::vector<PasswordForm> forms;
334   GetLogins(GetPasswordStore(index), forms);
335   return forms.size();
336 }
337
338 int GetVerifierPasswordCount() {
339   std::vector<PasswordForm> verifier_forms;
340   GetLogins(GetVerifierPasswordStore(), verifier_forms);
341   return verifier_forms.size();
342 }
343
344 PasswordForm CreateTestPasswordForm(int index) {
345   PasswordForm form;
346   form.signon_realm = kFakeSignonRealm;
347   form.origin = GURL(base::StringPrintf(kIndexedFakeOrigin, index));
348   form.username_value =
349       base::ASCIIToUTF16(base::StringPrintf("username%d", index));
350   form.password_value =
351       base::ASCIIToUTF16(base::StringPrintf("password%d", index));
352   form.date_created = base::Time::Now();
353   return form;
354 }
355
356 }  // namespace passwords_helper