OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/sync/test/integration/passwords_helper.h" | 5 #include "chrome/browser/sync/test/integration/passwords_helper.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 const std::vector<PasswordForm*>& result) OVERRIDE { | 47 const std::vector<PasswordForm*>& result) OVERRIDE { |
48 result_->clear(); | 48 result_->clear(); |
49 for (std::vector<PasswordForm*>::const_iterator it = result.begin(); | 49 for (std::vector<PasswordForm*>::const_iterator it = result.begin(); |
50 it != result.end(); | 50 it != result.end(); |
51 ++it) { | 51 ++it) { |
52 result_->push_back(**it); | 52 result_->push_back(**it); |
53 delete *it; | 53 delete *it; |
54 } | 54 } |
55 | 55 |
56 // Quit the message loop to wake up passwords_helper::GetLogins. | 56 // Quit the message loop to wake up passwords_helper::GetLogins. |
57 base::MessageLoopForUI::current()->Quit(); | 57 base::MessageLoopForUI::current()->Quit(); |
Nicolas Zea
2014/04/28 22:14:47
I wonder if we should instead not be using this, a
rlarocque
2014/04/28 23:18:58
In theory, I think switching to RunLoops here and
| |
58 } | 58 } |
59 | 59 |
60 private: | 60 private: |
61 std::vector<PasswordForm>* result_; | 61 std::vector<PasswordForm>* result_; |
62 | 62 |
63 DISALLOW_COPY_AND_ASSIGN(PasswordStoreConsumerHelper); | 63 DISALLOW_COPY_AND_ASSIGN(PasswordStoreConsumerHelper); |
64 }; | 64 }; |
65 | 65 |
66 } // namespace | 66 } // namespace |
67 | 67 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
200 | 200 |
201 // Helper class used in the implementation of | 201 // Helper class used in the implementation of |
202 // AwaitAllProfilesContainSamePasswordForms. | 202 // AwaitAllProfilesContainSamePasswordForms. |
203 class SamePasswordFormsChecker : public MultiClientStatusChangeChecker { | 203 class SamePasswordFormsChecker : public MultiClientStatusChangeChecker { |
204 public: | 204 public: |
205 SamePasswordFormsChecker(); | 205 SamePasswordFormsChecker(); |
206 virtual ~SamePasswordFormsChecker(); | 206 virtual ~SamePasswordFormsChecker(); |
207 | 207 |
208 virtual bool IsExitConditionSatisfied() OVERRIDE; | 208 virtual bool IsExitConditionSatisfied() OVERRIDE; |
209 virtual std::string GetDebugMessage() const OVERRIDE; | 209 virtual std::string GetDebugMessage() const OVERRIDE; |
210 | |
211 private: | |
212 bool in_progress_; | |
213 bool needs_recheck_; | |
210 }; | 214 }; |
211 | 215 |
212 SamePasswordFormsChecker::SamePasswordFormsChecker() | 216 SamePasswordFormsChecker::SamePasswordFormsChecker() |
213 : MultiClientStatusChangeChecker( | 217 : MultiClientStatusChangeChecker( |
214 sync_datatype_helper::test()->GetSyncServices()) {} | 218 sync_datatype_helper::test()->GetSyncServices()), |
219 in_progress_(false), | |
220 needs_recheck_(false) {} | |
215 | 221 |
216 SamePasswordFormsChecker::~SamePasswordFormsChecker() {} | 222 SamePasswordFormsChecker::~SamePasswordFormsChecker() {} |
217 | 223 |
224 // This method needs protection against re-entrancy. | |
225 // | |
226 // This function indirectly calls GetLogins(), which starts a RunLoop on the UI | |
227 // thread. This can be a problem, since the next task to execute could very | |
228 // well contain a ProfileSyncService::OnStateChanged() event, which would | |
229 // trigger another call to this here function, and start another layer of | |
230 // nested RunLoops. That makes the StatusChangeChecker's Quit() method | |
231 // ineffective. | |
232 // | |
233 // The work-around is to not allow re-entrancy. But we can't just drop | |
234 // IsExitConditionSatisifed() calls if one is already in progress. Instead, we | |
235 // set a flag to ask the current execution of IsExitConditionSatisfied() to be | |
236 // re-run. This ensures that the return value is always based on the most | |
237 // up-to-date state. | |
218 bool SamePasswordFormsChecker::IsExitConditionSatisfied() { | 238 bool SamePasswordFormsChecker::IsExitConditionSatisfied() { |
219 return AllProfilesContainSamePasswordForms(); | 239 if (in_progress_) { |
240 LOG(WARNING) << "Setting flag and returning early to prevent nesting."; | |
241 needs_recheck_ = true; | |
242 return false; | |
243 } | |
244 | |
245 // Keep retrying until we get a good reading. | |
246 bool result = false; | |
247 in_progress_ = true; | |
248 do { | |
249 needs_recheck_ = false; | |
250 result = AllProfilesContainSamePasswordForms(); | |
251 } while (needs_recheck_); | |
252 in_progress_ = false; | |
253 return result; | |
220 } | 254 } |
221 | 255 |
222 std::string SamePasswordFormsChecker::GetDebugMessage() const { | 256 std::string SamePasswordFormsChecker::GetDebugMessage() const { |
223 return "Waiting for matching passwords"; | 257 return "Waiting for matching passwords"; |
224 } | 258 } |
225 | 259 |
226 } // namespace | 260 } // namespace |
227 | 261 |
228 bool AwaitAllProfilesContainSamePasswordForms() { | 262 bool AwaitAllProfilesContainSamePasswordForms() { |
229 SamePasswordFormsChecker checker; | 263 SamePasswordFormsChecker checker; |
(...skipping 19 matching lines...) Expand all Loading... | |
249 form.origin = GURL(base::StringPrintf(kIndexedFakeOrigin, index)); | 283 form.origin = GURL(base::StringPrintf(kIndexedFakeOrigin, index)); |
250 form.username_value = | 284 form.username_value = |
251 base::ASCIIToUTF16(base::StringPrintf("username%d", index)); | 285 base::ASCIIToUTF16(base::StringPrintf("username%d", index)); |
252 form.password_value = | 286 form.password_value = |
253 base::ASCIIToUTF16(base::StringPrintf("password%d", index)); | 287 base::ASCIIToUTF16(base::StringPrintf("password%d", index)); |
254 form.date_created = base::Time::Now(); | 288 form.date_created = base::Time::Now(); |
255 return form; | 289 return form; |
256 } | 290 } |
257 | 291 |
258 } // namespace passwords_helper | 292 } // namespace passwords_helper |
OLD | NEW |