Chromium Code Reviews| 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 |