summaryrefslogtreecommitdiffstats
path: root/third_party
diff options
context:
space:
mode:
authorrouslan@chromium.org <rouslan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-17 08:26:42 +0000
committerrouslan@chromium.org <rouslan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-17 08:26:42 +0000
commit317b66eb10f6361698c03b3e6e25c15e123ff185 (patch)
treef65615e71e6cbece75066a9889a72aa1f0e9d807 /third_party
parent59044fc779e79172a0e6bd9edf9e00a9ac69bc1d (diff)
downloadchromium_src-317b66eb10f6361698c03b3e6e25c15e123ff185.zip
chromium_src-317b66eb10f6361698c03b3e6e25c15e123ff185.tar.gz
chromium_src-317b66eb10f6361698c03b3e6e25c15e123ff185.tar.bz2
Retry downloading rules for libaddressinput.
Retry downloading rules after 8, 16, 32, 64, 128, 256, and 512 seconds, while requestAutocomplete dialog is open. (512 seconds is ~8.5 minutes.) TEST=libaddressinput_unittests:FailingAddressValidatorTest.* BUG=343397 Review URL: https://codereview.chromium.org/392083002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283712 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
-rw-r--r--third_party/libaddressinput/chromium/chrome_address_validator.cc62
-rw-r--r--third_party/libaddressinput/chromium/chrome_address_validator.h32
-rw-r--r--third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc176
3 files changed, 226 insertions, 44 deletions
diff --git a/third_party/libaddressinput/chromium/chrome_address_validator.cc b/third_party/libaddressinput/chromium/chrome_address_validator.cc
index 2f2300a..13d7fecc 100644
--- a/third_party/libaddressinput/chromium/chrome_address_validator.cc
+++ b/third_party/libaddressinput/chromium/chrome_address_validator.cc
@@ -4,26 +4,21 @@
#include "third_party/libaddressinput/chromium/chrome_address_validator.h"
-#include <cstddef>
-#include <string>
-#include <vector>
+#include <cmath>
-#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
#include "third_party/libaddressinput/chromium/addressinput_util.h"
#include "third_party/libaddressinput/chromium/input_suggester.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_normalizer.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/downloader.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/preload_supplier.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
namespace autofill {
+namespace {
using ::i18n::addressinput::AddressData;
using ::i18n::addressinput::AddressField;
@@ -38,6 +33,11 @@ using ::i18n::addressinput::ADMIN_AREA;
using ::i18n::addressinput::DEPENDENT_LOCALITY;
using ::i18n::addressinput::POSTAL_CODE;
+// The maximum number attempts to load rules.
+static const int kMaxAttemptsNumber = 8;
+
+} // namespace
+
AddressValidator::AddressValidator(const std::string& validation_data_url,
scoped_ptr<Downloader> downloader,
scoped_ptr<Storage> storage,
@@ -50,12 +50,13 @@ AddressValidator::AddressValidator(const std::string& validation_data_url,
validator_(new ::i18n::addressinput::AddressValidator(supplier_.get())),
validated_(BuildCallback(this, &AddressValidator::Validated)),
rules_loaded_(BuildCallback(this, &AddressValidator::RulesLoaded)),
- load_rules_listener_(load_rules_listener) {}
+ load_rules_listener_(load_rules_listener),
+ weak_factory_(this) {}
AddressValidator::~AddressValidator() {}
void AddressValidator::LoadRules(const std::string& region_code) {
- DCHECK(supplier_);
+ attempts_number_[region_code] = 0;
supplier_->LoadRules(region_code, *rules_loaded_);
}
@@ -63,9 +64,6 @@ AddressValidator::Status AddressValidator::ValidateAddress(
const AddressData& address,
const FieldProblemMap* filter,
FieldProblemMap* problems) const {
- DCHECK(supplier_);
- DCHECK(validator_);
-
if (supplier_->IsPending(address.region_code)) {
if (problems)
addressinput::ValidateRequiredFields(address, filter, problems);
@@ -96,9 +94,6 @@ AddressValidator::Status AddressValidator::GetSuggestions(
AddressField focused_field,
size_t suggestion_limit,
std::vector<AddressData>* suggestions) const {
- DCHECK(supplier_);
- DCHECK(input_suggester_);
-
if (supplier_->IsPending(user_input.region_code))
return RULES_NOT_READY;
@@ -121,10 +116,6 @@ AddressValidator::Status AddressValidator::GetSuggestions(
bool AddressValidator::CanonicalizeAdministrativeArea(
AddressData* address) const {
- DCHECK(address);
- DCHECK(supplier_);
- DCHECK(normalizer_);
-
if (!supplier_->IsLoaded(address->region_code))
return false;
@@ -136,7 +127,12 @@ bool AddressValidator::CanonicalizeAdministrativeArea(
return true;
}
-AddressValidator::AddressValidator() : load_rules_listener_(NULL) {}
+AddressValidator::AddressValidator()
+ : load_rules_listener_(NULL), weak_factory_(this) {}
+
+base::TimeDelta AddressValidator::GetBaseRetryPeriod() const {
+ return base::TimeDelta::FromSeconds(8);
+}
void AddressValidator::Validated(bool success,
const AddressData&,
@@ -145,10 +141,26 @@ void AddressValidator::Validated(bool success,
}
void AddressValidator::RulesLoaded(bool success,
- const std::string& country_code,
+ const std::string& region_code,
int) {
if (load_rules_listener_)
- load_rules_listener_->OnAddressValidationRulesLoaded(country_code, success);
+ load_rules_listener_->OnAddressValidationRulesLoaded(region_code, success);
+
+ // Count the first failed attempt to load rules as well.
+ if (success || attempts_number_[region_code] + 1 >= kMaxAttemptsNumber)
+ return;
+
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&AddressValidator::RetryLoadRules,
+ weak_factory_.GetWeakPtr(),
+ region_code),
+ GetBaseRetryPeriod() * pow(2, attempts_number_[region_code]++));
+}
+
+void AddressValidator::RetryLoadRules(const std::string& region_code) {
+ // Do not reset retry count.
+ supplier_->LoadRules(region_code, *rules_loaded_);
}
} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/chrome_address_validator.h b/third_party/libaddressinput/chromium/chrome_address_validator.h
index 49875c8..ba4b413 100644
--- a/third_party/libaddressinput/chromium/chrome_address_validator.h
+++ b/third_party/libaddressinput/chromium/chrome_address_validator.h
@@ -5,12 +5,14 @@
#ifndef THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_CHROME_ADDRESS_VALIDATOR_H_
#define THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_CHROME_ADDRESS_VALIDATOR_H_
-#include <cstddef>
+#include <map>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h"
@@ -35,14 +37,14 @@ class LoadRulesListener {
public:
virtual ~LoadRulesListener() {}
- // Called when the validation rules for the |country_code| have been loaded.
- // The validation rules include the generic rules for the |country_code| and
+ // Called when the validation rules for the |region_code| have been loaded.
+ // The validation rules include the generic rules for the |region_code| and
// specific rules for the country's administrative areas, localities, and
// dependent localities. If a country has language-specific validation rules,
// then these are also loaded.
//
// The |success| parameter is true when the rules were loaded successfully.
- virtual void OnAddressValidationRulesLoaded(const std::string& country_code,
+ virtual void OnAddressValidationRulesLoaded(const std::string& region_code,
bool success) = 0;
};
@@ -138,12 +140,15 @@ class AddressValidator {
virtual bool CanonicalizeAdministrativeArea(
::i18n::addressinput::AddressData* address) const;
- private:
- friend class MockAddressValidator;
-
+ protected:
// Constructor used only for MockAddressValidator.
AddressValidator();
+ // Returns the period of time to wait between the first attempt's failure and
+ // the second attempt's initiation to load rules. Exposed for testing.
+ virtual base::TimeDelta GetBaseRetryPeriod() const;
+
+ private:
// Verifies that |validator_| succeeded. Invoked by |validated_| callback.
void Validated(bool success,
const ::i18n::addressinput::AddressData&,
@@ -151,7 +156,10 @@ class AddressValidator {
// Invokes the |load_rules_listener_|, if it's not NULL. Called by
// |rules_loaded_| callback.
- void RulesLoaded(bool success, const std::string& country_code, int);
+ void RulesLoaded(bool success, const std::string& region_code, int);
+
+ // Retries loading rules without resetting the retry counter.
+ void RetryLoadRules(const std::string& region_code);
// Loads and stores aggregate rules at COUNTRY level.
const scoped_ptr< ::i18n::addressinput::PreloadSupplier> supplier_;
@@ -178,6 +186,14 @@ class AddressValidator {
// NULL.
LoadRulesListener* const load_rules_listener_;
+ // A mapping of region codes to the number of attempts to retry loading rules.
+ std::map<std::string, int> attempts_number_;
+
+ // Member variables should appear before the WeakPtrFactory, to ensure that
+ // any WeakPtrs to AddressValidator are invalidated before its members
+ // variable's destructors are executed, rendering them invalid.
+ base::WeakPtrFactory<AddressValidator> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(AddressValidator);
};
diff --git a/third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc b/third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc
index 906d0a6..f72cbd9 100644
--- a/third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc
+++ b/third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc
@@ -8,25 +8,19 @@
#include <string>
#include <vector>
-#include "base/basictypes.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_problem.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/downloader.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
#include "third_party/libaddressinput/src/cpp/test/fake_downloader.h"
-namespace {
+namespace autofill {
-using ::autofill::AddressValidator;
-using ::autofill::LoadRulesListener;
using ::i18n::addressinput::AddressData;
using ::i18n::addressinput::AddressField;
using ::i18n::addressinput::AddressProblem;
@@ -84,7 +78,7 @@ class AddressValidatorTest : public testing::Test, LoadRulesListener {
DISALLOW_COPY_AND_ASSIGN(AddressValidatorTest);
};
-// Use this text fixture if you're going to use a region with a large set of
+// Use this test fixture if you're going to use a region with a large set of
// validation rules. All rules should be loaded in SetUpTestCase().
class LargeAddressValidatorTest : public testing::Test {
protected:
@@ -737,4 +731,164 @@ TEST_F(AddressValidatorTest,
EXPECT_TRUE(problems.empty());
}
-} // namespace
+// Use this test fixture for configuring the number of failed attempts to load
+// rules.
+class FailingAddressValidatorTest : public testing::Test, LoadRulesListener {
+ protected:
+ // A validator that retries loading rules without delay.
+ class TestAddressValidator : public AddressValidator {
+ public:
+ // Takes ownership of |downloader| and |storage|.
+ TestAddressValidator(
+ const std::string& validation_data_url,
+ scoped_ptr< ::i18n::addressinput::Downloader> downloader,
+ scoped_ptr< ::i18n::addressinput::Storage> storage,
+ LoadRulesListener* load_rules_listener)
+ : AddressValidator(validation_data_url,
+ downloader.Pass(),
+ storage.Pass(),
+ load_rules_listener) {}
+
+ virtual ~TestAddressValidator() {}
+
+ protected:
+ virtual base::TimeDelta GetBaseRetryPeriod() const OVERRIDE {
+ return base::TimeDelta::FromSeconds(0);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestAddressValidator);
+ };
+
+ // A downloader that always fails |failures_number| times before downloading
+ // data.
+ class FailingDownloader : public Downloader {
+ public:
+ explicit FailingDownloader() : failures_number_(0), attempts_number_(0) {}
+ virtual ~FailingDownloader() {}
+
+ // Sets the number of times to fail before downloading data.
+ void set_failures_number(int failures_number) {
+ failures_number_ = failures_number;
+ }
+
+ // Downloader implementation.
+ // Always fails for the first |failures_number| times.
+ virtual void Download(const std::string& url,
+ const Callback& callback) const OVERRIDE {
+ ++attempts_number_;
+ // |callback| takes ownership of the |new std::string|.
+ if (failures_number_-- > 0)
+ callback(false, url, new std::string);
+ else
+ actual_downloader_.Download(url, callback);
+ }
+
+ // Returns the number of download attempts.
+ int attempts_number() const { return attempts_number_; }
+
+ private:
+ // The number of times to fail before downloading data.
+ mutable int failures_number_;
+
+ // The number of times Download was called.
+ mutable int attempts_number_;
+
+ // The downloader to use for successful downloads.
+ FakeDownloader actual_downloader_;
+
+ DISALLOW_COPY_AND_ASSIGN(FailingDownloader);
+ };
+
+ FailingAddressValidatorTest()
+ : downloader_(new FailingDownloader),
+ validator_(
+ new TestAddressValidator(FakeDownloader::kFakeAggregateDataUrl,
+ scoped_ptr<Downloader>(downloader_),
+ scoped_ptr<Storage>(new NullStorage),
+ this)),
+ load_rules_success_(false) {}
+
+ virtual ~FailingAddressValidatorTest() {}
+
+ FailingDownloader* downloader_; // Owned by |validator_|.
+ scoped_ptr<AddressValidator> validator_;
+ bool load_rules_success_;
+
+ private:
+ // LoadRulesListener implementation.
+ virtual void OnAddressValidationRulesLoaded(const std::string&,
+ bool success) OVERRIDE {
+ load_rules_success_ = success;
+ }
+
+ base::MessageLoop ui_;
+
+ DISALLOW_COPY_AND_ASSIGN(FailingAddressValidatorTest);
+};
+
+// The validator will attempt to load rules at most 8 times.
+TEST_F(FailingAddressValidatorTest, RetryLoadingRulesHasLimit) {
+ downloader_->set_failures_number(99);
+ validator_->LoadRules("CH");
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(load_rules_success_);
+ EXPECT_EQ(8, downloader_->attempts_number());
+}
+
+// The validator will load rules successfully if the downloader returns data
+// before the maximum number of retries.
+TEST_F(FailingAddressValidatorTest, RuleRetryingWillSucceed) {
+ downloader_->set_failures_number(4);
+ validator_->LoadRules("CH");
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(load_rules_success_);
+ EXPECT_EQ(5, downloader_->attempts_number());
+}
+
+// The delayed task to retry loading rules should stop (instead of crashing) if
+// the validator is destroyed before it fires.
+TEST_F(FailingAddressValidatorTest, DestroyedValidatorStopsRetries) {
+ downloader_->set_failures_number(4);
+ validator_->LoadRules("CH");
+
+ // Destroy the validator.
+ validator_.reset();
+
+ // Fire the delayed task to retry loading rules.
+ EXPECT_NO_FATAL_FAILURE(base::RunLoop().RunUntilIdle());
+}
+
+// Each call to LoadRules should reset the number of retry attempts. If the
+// first call to LoadRules exceeded the maximum number of retries, the second
+// call to LoadRules should start counting the retries from zero.
+TEST_F(FailingAddressValidatorTest, LoadingRulesSecondTimeSucceeds) {
+ downloader_->set_failures_number(11);
+ validator_->LoadRules("CH");
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(load_rules_success_);
+ EXPECT_EQ(8, downloader_->attempts_number());
+
+ validator_->LoadRules("CH");
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(load_rules_success_);
+ EXPECT_EQ(12, downloader_->attempts_number());
+}
+
+// Calling LoadRules("CH") and LoadRules("GB") simultaneously should attempt to
+// load both rules up to the maximum number of attempts for each region.
+TEST_F(FailingAddressValidatorTest, RegionsShouldRetryIndividually) {
+ downloader_->set_failures_number(99);
+ validator_->LoadRules("CH");
+ validator_->LoadRules("GB");
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(load_rules_success_);
+ EXPECT_EQ(16, downloader_->attempts_number());
+}
+
+} // namespace autofill