Skip to content

Commit

Permalink
[fuchsia] Add locale support to FuchsiaIntlProfileWatcher
Browse files Browse the repository at this point in the history
FuchsiaIntlProfileWatcher and confirm both the initialization values
were correctly reported, as well as updates to the underlying
PropertyProvider were sent to the registered ProfileChangeCallback.

Bug: 1156404, b/168161909
Test: intl_profile_watcher_unittest
Test: Added a small bit of code to utilize the
Change-Id: I39fd7b462e7b0571b1acb242a7a0c8253213ec7d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2577884
Commit-Queue: Aaron Knobloch <aknobloch@google.com>
Reviewed-by: David Dorwin <ddorwin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#835502}
  • Loading branch information
Aaron Knobloch authored and Chromium LUCI CQ committed Dec 10, 2020
1 parent c6c66b7 commit 910f031
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 52 deletions.
42 changes: 34 additions & 8 deletions base/fuchsia/intl_profile_watcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ std::string FuchsiaIntlProfileWatcher::GetPrimaryTimeZoneIdFromProfile(

const std::vector<::fuchsia::intl::TimeZoneId>& time_zones =
profile.time_zones();
if (time_zones.size() == 0) {
DLOG(WARNING) << "Profile contains an empty time zones list.";
if (time_zones.empty()) {
DLOG(ERROR) << "Profile contains an empty time zones list.";
return std::string();
}

Expand All @@ -67,23 +67,49 @@ std::string FuchsiaIntlProfileWatcher::GetPrimaryTimeZoneIdFromProfile(
// static
std::string
FuchsiaIntlProfileWatcher::GetPrimaryTimeZoneIdForIcuInitialization() {
::fuchsia::intl::PropertyProviderSyncPtr provider;
ComponentContextForProcess()->svc()->Connect(provider.NewRequest());
return GetPrimaryTimeZoneIdFromPropertyProvider(std::move(provider));
return GetPrimaryTimeZoneIdFromProfile(GetCurrentProfileSync());
}

// static
std::string FuchsiaIntlProfileWatcher::GetPrimaryTimeZoneIdFromPropertyProvider(
std::string FuchsiaIntlProfileWatcher::GetPrimaryLocaleIdFromProfile(
const ::fuchsia::intl::Profile& profile) {
if (!profile.has_locales()) {
DLOG(ERROR) << "Profile does not contain locale information.";
return std::string();
}

const std::vector<::fuchsia::intl::LocaleId>& locale_preferences =
profile.locales();
if (locale_preferences.empty()) {
DLOG(ERROR) << "Profile contains an empty locale list.";
return std::string();
}

return locale_preferences[0].id;
}

// static
std::string FuchsiaIntlProfileWatcher::GetPrimaryLocaleIdForInitialization() {
return GetPrimaryLocaleIdFromProfile(GetCurrentProfileSync());
}

// static
Profile FuchsiaIntlProfileWatcher::GetProfileFromPropertyProvider(
::fuchsia::intl::PropertyProviderSyncPtr property_provider) {
DCHECK(property_provider.is_bound());
Profile profile;
zx_status_t status = property_provider->GetProfile(&profile);
if (status != ZX_OK) {
ZX_DLOG(ERROR, status) << "Failed to get intl Profile";
return std::string();
}
return profile;
}

return GetPrimaryTimeZoneIdFromProfile(profile);
// static
::fuchsia::intl::Profile FuchsiaIntlProfileWatcher::GetCurrentProfileSync() {
::fuchsia::intl::PropertyProviderSyncPtr provider;
ComponentContextForProcess()->svc()->Connect(provider.NewRequest());
return GetProfileFromPropertyProvider(std::move(provider));
}

} // namespace base
21 changes: 16 additions & 5 deletions base/fuchsia/intl_profile_watcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class BASE_EXPORT FuchsiaIntlProfileWatcher {
~FuchsiaIntlProfileWatcher();

// Returns the ID of the primary time zone in |profile|.
// Returns the empty string if the ID cannot be obtained.
// Returns an empty string if the ID cannot be obtained.
static std::string GetPrimaryTimeZoneIdFromProfile(
const ::fuchsia::intl::Profile& profile);

Expand All @@ -41,19 +41,30 @@ class BASE_EXPORT FuchsiaIntlProfileWatcher {
// be used for ICU initialization.
static std::string GetPrimaryTimeZoneIdForIcuInitialization();

// Returns the ID of the primary locale preference in |profile|.
// Returns an empty string if the ID cannot be obtained.
static std::string GetPrimaryLocaleIdFromProfile(
const ::fuchsia::intl::Profile& profile);

// Returns the ID of the primary locale preference for the system.
// Returns an empty string if the ID cannot be obtained.
// This is a synchronous blocking call to the system service, and should only
// be used for first value initialization.
static std::string GetPrimaryLocaleIdForInitialization();

private:
friend class GetPrimaryTimeZoneIdFromPropertyProviderTest;
friend class GetValuesFromIntlPropertyProviderTest;
friend class IntlProfileWatcherTest;

FuchsiaIntlProfileWatcher(
::fuchsia::intl::PropertyProviderPtr property_provider,
ProfileChangeCallback on_profile_changed);

// Returns the ID of the primary time zone from the profile obtained from
// |property_provider|. Returns the empty string if the ID cannot be obtained.
static std::string GetPrimaryTimeZoneIdFromPropertyProvider(
static ::fuchsia::intl::Profile GetProfileFromPropertyProvider(
::fuchsia::intl::PropertyProviderSyncPtr property_provider);

static ::fuchsia::intl::Profile GetCurrentProfileSync();

::fuchsia::intl::PropertyProviderPtr property_provider_;
const ProfileChangeCallback on_profile_changed_;
};
Expand Down
154 changes: 115 additions & 39 deletions base/fuchsia/intl_profile_watcher_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,36 @@ namespace {
const char kPrimaryTimeZoneName[] = "Australia/Darwin";
const char kSecondaryTimeZoneName[] = "Africa/Djibouti";

void CopyIdsToTimeZoneIds(
const std::vector<std::string>& zone_ids,
std::vector<::fuchsia::intl::TimeZoneId>* time_zone_ids) {
time_zone_ids->clear();
for (auto id : zone_ids) {
::fuchsia::intl::TimeZoneId time_zone_id;
time_zone_id.id = id;
time_zone_ids->push_back(time_zone_id);
const char kPrimaryLocaleName[] = "en-US";
const char kSecondaryLocaleName[] = "es-419";

template <typename FuchsiaStruct>
void CopyIdsToFuchsiaStruct(const std::vector<std::string>& raw_ids,
std::vector<FuchsiaStruct>* fuchsia_ids) {
fuchsia_ids->clear();
for (auto id : raw_ids) {
FuchsiaStruct fuchsia_id;
fuchsia_id.id = id;
fuchsia_ids->push_back(fuchsia_id);
}
}

Profile CreateProfileWithTimeZones(const std::vector<std::string>& zone_ids) {
Profile profile;
std::vector<::fuchsia::intl::TimeZoneId> time_zone_ids;
CopyIdsToTimeZoneIds(zone_ids, &time_zone_ids);
CopyIdsToFuchsiaStruct(zone_ids, &time_zone_ids);
profile.set_time_zones(time_zone_ids);
return profile;
}

Profile CreateProfileWithLocales(const std::vector<std::string>& locale_ids) {
Profile profile;
std::vector<::fuchsia::intl::LocaleId> fuchsia_locale_ids;
CopyIdsToFuchsiaStruct(locale_ids, &fuchsia_locale_ids);
profile.set_locales(fuchsia_locale_ids);
return profile;
}

// Partial fake implementation of a PropertyProvider.
class FakePropertyProvider
: public ::fuchsia::intl::testing::PropertyProvider_TestBase {
Expand All @@ -66,7 +77,10 @@ class FakePropertyProvider

void Close() { binding_.Close(ZX_ERR_PEER_CLOSED); }
void SetTimeZones(const std::vector<std::string>& zone_ids) {
CopyIdsToTimeZoneIds(zone_ids, &time_zone_ids_);
CopyIdsToFuchsiaStruct(zone_ids, &time_zone_ids_);
}
void SetLocales(const std::vector<std::string>& locale_ids) {
CopyIdsToFuchsiaStruct(locale_ids, &fuchsia_locale_ids_);
}
void NotifyChange() { binding_.events().OnChange(); }

Expand All @@ -75,6 +89,7 @@ class FakePropertyProvider
::fuchsia::intl::PropertyProvider::GetProfileCallback callback) override {
Profile profile;
profile.set_time_zones(time_zone_ids_);
profile.set_locales(fuchsia_locale_ids_);
callback(std::move(profile));
}
void NotImplemented_(const std::string& name) override {
Expand All @@ -85,6 +100,7 @@ class FakePropertyProvider
::fidl::Binding<::fuchsia::intl::PropertyProvider> binding_;

std::vector<::fuchsia::intl::TimeZoneId> time_zone_ids_;
std::vector<::fuchsia::intl::LocaleId> fuchsia_locale_ids_;
};

class FakePropertyProviderAsync {
Expand All @@ -110,6 +126,10 @@ class FakePropertyProviderAsync {
property_provider_.Post(FROM_HERE, &FakePropertyProvider::SetTimeZones,
zone_ids);
}
void SetLocales(const std::vector<std::string>& locale_ids) {
property_provider_.Post(FROM_HERE, &FakePropertyProvider::SetLocales,
locale_ids);
}
void NotifyChange() {
property_provider_.Post(FROM_HERE, &FakePropertyProvider::NotifyChange);
}
Expand All @@ -121,20 +141,32 @@ class FakePropertyProviderAsync {

} // namespace

class GetPrimaryTimeZoneIdFromPropertyProviderTest : public testing::Test {
class GetValuesFromIntlPropertyProviderTest : public testing::Test {
public:
GetPrimaryTimeZoneIdFromPropertyProviderTest()
GetValuesFromIntlPropertyProviderTest()
: property_provider_(property_provider_ptr_.NewRequest()) {}
GetPrimaryTimeZoneIdFromPropertyProviderTest(
const GetPrimaryTimeZoneIdFromPropertyProviderTest&) = delete;
GetPrimaryTimeZoneIdFromPropertyProviderTest& operator=(
const GetPrimaryTimeZoneIdFromPropertyProviderTest&) = delete;
~GetPrimaryTimeZoneIdFromPropertyProviderTest() override = default;
GetValuesFromIntlPropertyProviderTest(
const GetValuesFromIntlPropertyProviderTest&) = delete;
GetValuesFromIntlPropertyProviderTest& operator=(
const GetValuesFromIntlPropertyProviderTest&) = delete;
~GetValuesFromIntlPropertyProviderTest() override = default;

protected:
static std::string GetPrimaryTimeZoneIdFromPropertyProvider(
std::string GetPrimaryLocaleId() {
Profile profile =
GetProfileFromPropertyProvider(std::move(property_provider_ptr_));
return FuchsiaIntlProfileWatcher::GetPrimaryLocaleIdFromProfile(profile);
}

std::string GetPrimaryTimeZoneId() {
Profile profile =
GetProfileFromPropertyProvider(std::move(property_provider_ptr_));
return FuchsiaIntlProfileWatcher::GetPrimaryTimeZoneIdFromProfile(profile);
}

static Profile GetProfileFromPropertyProvider(
::fuchsia::intl::PropertyProviderSyncPtr property_provider) {
return FuchsiaIntlProfileWatcher::GetPrimaryTimeZoneIdFromPropertyProvider(
return FuchsiaIntlProfileWatcher::GetProfileFromPropertyProvider(
std::move(property_provider));
}

Expand Down Expand Up @@ -183,40 +215,61 @@ TEST(IntlServiceNotAvailableTest, FuchsiaIntlProfileWatcher) {
run_loop.RunUntilIdle();
}

TEST_F(GetPrimaryTimeZoneIdFromPropertyProviderTest, RemoteNotBound) {
TEST_F(GetValuesFromIntlPropertyProviderTest,
GetPrimaryTimeZoneId_RemoteNotBound) {
// Simulate the service not actually being available.
property_provider_.Close();
EXPECT_STREQ("", GetPrimaryTimeZoneIdFromPropertyProvider(
std::move(property_provider_ptr_))
.c_str());
EXPECT_STREQ("", GetPrimaryTimeZoneId().c_str());
}

TEST_F(GetPrimaryTimeZoneIdFromPropertyProviderTest, NoZones) {
EXPECT_STREQ("", GetPrimaryTimeZoneIdFromPropertyProvider(
std::move(property_provider_ptr_))
.c_str());
TEST_F(GetValuesFromIntlPropertyProviderTest, GetPrimaryTimeZoneId_NoZones) {
EXPECT_STREQ("", GetPrimaryTimeZoneId().c_str());
}

TEST_F(GetPrimaryTimeZoneIdFromPropertyProviderTest, SingleZone) {
TEST_F(GetValuesFromIntlPropertyProviderTest, GetPrimaryTimeZoneId_SingleZone) {
property_provider_.SetTimeZones({kPrimaryTimeZoneName});
EXPECT_STREQ(kPrimaryTimeZoneName, GetPrimaryTimeZoneIdFromPropertyProvider(
std::move(property_provider_ptr_))
.c_str());
EXPECT_STREQ(kPrimaryTimeZoneName, GetPrimaryTimeZoneId().c_str());
}

TEST_F(GetPrimaryTimeZoneIdFromPropertyProviderTest, SingleZoneIsEmpty) {
TEST_F(GetValuesFromIntlPropertyProviderTest,
GetPrimaryTimeZoneId_SingleZoneIsEmpty) {
property_provider_.SetTimeZones({""});
EXPECT_STREQ("", GetPrimaryTimeZoneIdFromPropertyProvider(
std::move(property_provider_ptr_))
.c_str());
EXPECT_STREQ("", GetPrimaryTimeZoneId().c_str());
}

TEST_F(GetPrimaryTimeZoneIdFromPropertyProviderTest, MoreThanOneZone) {
TEST_F(GetValuesFromIntlPropertyProviderTest,
GetPrimaryTimeZoneId_MoreThanOneZone) {
property_provider_.SetTimeZones(
{kPrimaryTimeZoneName, kSecondaryTimeZoneName});
EXPECT_STREQ(kPrimaryTimeZoneName, GetPrimaryTimeZoneIdFromPropertyProvider(
std::move(property_provider_ptr_))
.c_str());
EXPECT_STREQ(kPrimaryTimeZoneName, GetPrimaryTimeZoneId().c_str());
}

TEST_F(GetValuesFromIntlPropertyProviderTest,
GetPrimaryLocaleId_RemoteNotBound) {
// Simulate the service not actually being available.
property_provider_.Close();
EXPECT_STREQ("", GetPrimaryLocaleId().c_str());
}

TEST_F(GetValuesFromIntlPropertyProviderTest, GetPrimaryLocaleId_NoZones) {
EXPECT_STREQ("", GetPrimaryLocaleId().c_str());
}

TEST_F(GetValuesFromIntlPropertyProviderTest, GetPrimaryLocaleId_SingleLocale) {
property_provider_.SetLocales({kPrimaryLocaleName});
EXPECT_STREQ(kPrimaryLocaleName, GetPrimaryLocaleId().c_str());
}

TEST_F(GetValuesFromIntlPropertyProviderTest,
GetPrimaryLocaleId_SingleLocaleIsEmpty) {
property_provider_.SetLocales({""});
EXPECT_STREQ("", GetPrimaryLocaleId().c_str());
}

TEST_F(GetValuesFromIntlPropertyProviderTest,
GetPrimaryLocaleId_MoreThanOneLocale) {
property_provider_.SetLocales({kPrimaryLocaleName, kSecondaryLocaleName});
EXPECT_STREQ(kPrimaryLocaleName, GetPrimaryLocaleId().c_str());
}

TEST_F(IntlProfileWatcherTest, NoZones_NoNotification) {
Expand Down Expand Up @@ -305,4 +358,27 @@ TEST(IntlProfileWatcherGetPrimaryTimeZoneIdFromProfileTest, TwoZones) {
{kPrimaryTimeZoneName, kSecondaryTimeZoneName})));
}

TEST(IntlProfileWatcherGetPrimaryLocaleIdFromProfileTest, NoLocales) {
EXPECT_EQ(
"", FuchsiaIntlProfileWatcher::GetPrimaryLocaleIdFromProfile(Profile()));
}

TEST(IntlProfileWatcherGetPrimaryLocaleIdFromProfileTest, EmptyLocalesList) {
EXPECT_EQ("", FuchsiaIntlProfileWatcher::GetPrimaryLocaleIdFromProfile(
CreateProfileWithLocales({})));
}

TEST(IntlProfileWatcherGetPrimaryLocaleIdFromProfileTest, OneLocale) {
EXPECT_EQ(kPrimaryLocaleName,
FuchsiaIntlProfileWatcher::GetPrimaryLocaleIdFromProfile(
CreateProfileWithLocales({kPrimaryLocaleName})));
}

TEST(IntlProfileWatcherGetPrimaryLocaleIdFromProfileTest, MultipleLocales) {
EXPECT_EQ(kPrimaryLocaleName,
FuchsiaIntlProfileWatcher::GetPrimaryLocaleIdFromProfile(
CreateProfileWithLocales(
{kPrimaryLocaleName, kSecondaryLocaleName})));
}

} // namespace base

0 comments on commit 910f031

Please sign in to comment.