DescriptionCountryNames: Separate data creation from usage
==Goal==
Fix a race condition in CountryNames-related code without complicating
it significantly.
==Non-goal==
Any deeper refactoring not necessary to fix the above race
condition. A discussion is needed to see whether once could avoid the
Singleton business and use some more common ways to store the country names
data (a database?), as well as whether it is necessary to compute it in
run-time. But that is explicitly out of scope of this CL.
==Content==
This CL makes CountryNames create its data (mappings from country names to
country codes and the appropriate collators for hashing the country names) on
construction, rather than on demand.
The main purpose of this change is to eliminate race conditions. Before this
CL, multiple threads could have trigger the data creation, and it is believed
to have caused data corruption and crashes.
Because the CountryNames creation is guaranteed by Singleton to only happen
once, it solves the threading issues.
However, there are caveats:
(Caveat A) CountryNames cannot get constructor arguments,
being created through Singleton's get(). But it needs to know which locale
Chrome is using. To circumvent this, it gets the information from a global
static string, and relies on the callsites of CountryNames to ensure
initialisation of this string.
To make that happen, every instance of AutofillManager ensures on its
construction, that said string is initialised. This is a bit clumsy (there is
an AutofillManager for each tab, but this pointer only needs to be initialised
once per Chrome's execution), but works -- CountryNames are never used earlier
than the first AutofillManager is constructed.
Also, while initialising the string is not guarded by any mutex, it is
safe -- AutofillManager gets constructed on the UI thread, so there are not
more concurrent constructions. And once the string is set, it is never set
again, so a constructed CountryNames can read it safely on any thread.
(Caveat B) Before this CL, the code was capable of generating more data for a
newly added locale on the fly. After this CL, it will only work for the locale
of the program during the CountryNames creation (and en_US as a fallback).
Note that Chrome does not seem to be able to change the language without
restart, so this should be no concern. The only unknown for me is CrOS -- I'm
not sure whether a new CountryNames instance is created for each user session.
But my suggestion is to wait with making the code more flexible until the
more systematic fix to the way it generates and stores the CountryNames data.
Finally, this CL adds a way to construct CountryNames with an explicit locale
in tests, and uses it in the appropriate unit tests.
BUG=571610
Committed: https://crrev.com/f39cbace358fe626f0f07e32f4e66b78ca589038
Cr-Commit-Position: refs/heads/master@{#371226}
Patch Set 1 #Patch Set 2 : Fix comments #Patch Set 3 : Fix branch dependency #Patch Set 4 : Add implementation in AwAutofillClient to fix Android compilation #Patch Set 5 : Just rebased #Patch Set 6 : Fix Android #Patch Set 7 : Fix a glitch in rebase #Patch Set 8 : More Android fixes #
Total comments: 29
Patch Set 9 : Just rebased #Patch Set 10 : Comments addressed #Patch Set 11 : Fix tests #Patch Set 12 : One more comment addressed + checking equality of locales, not locale strings in SetLocaleString #Patch Set 13 : Also set locale in the test constructor #Patch Set 14 : Format #Patch Set 15 : Revert the addition to AutofillClient #Patch Set 16 : Yet more tests fixed #Patch Set 17 : Fix compile #Patch Set 18 : One more test fixed #Patch Set 19 : Set CountryNames locale also from PersonalDataManager #
Total comments: 4
Patch Set 20 : No const + no double init #Patch Set 21 : Remove #include added by accident #Patch Set 22 : Just rebased #Messages
Total messages: 26 (10 generated)
|