Skip to content

Commit

Permalink
[fuchsia] Use fuchsia.intl.PropertyProvider to get time zone
Browse files Browse the repository at this point in the history
Adds Fuchsia support to InitializeIcuTimeZone() and implements
TimeZoneMonitorFuchsia.

This causes Chrome's internal time zone to match the system.
Note: deprecatedtimezone is still used for exploded time and will be
replaced in a separate CL.

Bug: 985946
Test: JavaScript `Date()` displays the correct local time and zone.
Change-Id: I3ab495ac277f5a53f60a3f51e8b128a12370a99b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1877809
Commit-Queue: David Dorwin <ddorwin@chromium.org>
Reviewed-by: Yuchen Liu <yucliu@chromium.org>
Reviewed-by: Ken Rockot <rockot@google.com>
Reviewed-by: Will Harris <wfh@chromium.org>
Reviewed-by: Wez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#721862}
  • Loading branch information
ddorwin authored and Commit Bot committed Dec 5, 2019
1 parent ab46869 commit 36d173b
Show file tree
Hide file tree
Showing 16 changed files with 536 additions and 6 deletions.
5 changes: 5 additions & 0 deletions base/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1544,6 +1544,8 @@ jumbo_component("base") {
"fuchsia/filtered_service_directory.h",
"fuchsia/fuchsia_logging.cc",
"fuchsia/fuchsia_logging.h",
"fuchsia/intl_profile_watcher.cc",
"fuchsia/intl_profile_watcher.h",
"fuchsia/scoped_service_binding.cc",
"fuchsia/scoped_service_binding.h",
"fuchsia/service_directory.cc",
Expand Down Expand Up @@ -1615,6 +1617,7 @@ jumbo_component("base") {
"//third_party/fuchsia-sdk/sdk:async-loop-default",
"//third_party/fuchsia-sdk/sdk:fidl",
"//third_party/fuchsia-sdk/sdk:fuchsia-deprecatedtimezone",
"//third_party/fuchsia-sdk/sdk:fuchsia-intl",
"//third_party/fuchsia-sdk/sdk:fuchsia-sys",
"//third_party/fuchsia-sdk/sdk:syslog",
"//third_party/fuchsia-sdk/sdk:vfs_cpp",
Expand Down Expand Up @@ -3039,6 +3042,7 @@ test("base_unittests") {
"files/file_descriptor_watcher_posix_unittest.cc",
"fuchsia/file_utils_unittest.cc",
"fuchsia/filtered_service_directory_unittest.cc",
"fuchsia/intl_profile_watcher_unittest.cc",
"fuchsia/scoped_service_binding_unittest.cc",
"fuchsia/service_directory_test_base.cc",
"fuchsia/service_directory_test_base.h",
Expand All @@ -3057,6 +3061,7 @@ test("base_unittests") {
"//third_party/fuchsia-sdk/sdk:async",
"//third_party/fuchsia-sdk/sdk:async-default",
"//third_party/fuchsia-sdk/sdk:fdio",
"//third_party/fuchsia-sdk/sdk:fuchsia-intl",
"//third_party/fuchsia-sdk/sdk:fuchsia-logger",
"//third_party/fuchsia-sdk/sdk:fuchsia-sys",
"//third_party/fuchsia-sdk/sdk:sys_cpp",
Expand Down
88 changes: 88 additions & 0 deletions base/fuchsia/intl_profile_watcher.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/fuchsia/intl_profile_watcher.h"

#include <fuchsia/intl/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h>
#include <string>
#include <vector>

#include "base/fuchsia/default_context.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/strings/string_piece.h"

using ::fuchsia::intl::Profile;

namespace base {
namespace fuchsia {

IntlProfileWatcher::IntlProfileWatcher(ProfileChangeCallback on_profile_changed)
: IntlProfileWatcher(ComponentContextForCurrentProcess()
->svc()
->Connect<::fuchsia::intl::PropertyProvider>(),
on_profile_changed) {}

IntlProfileWatcher::IntlProfileWatcher(
::fuchsia::intl::PropertyProviderPtr property_provider,
ProfileChangeCallback on_profile_changed)
: property_provider_(std::move(property_provider)),
on_profile_changed_(std::move(on_profile_changed)) {
DCHECK(property_provider_.is_bound());
DCHECK(on_profile_changed_);

property_provider_.set_error_handler([](zx_status_t status) {
ZX_LOG(ERROR, status) << "intl.PropertyProvider disconnected. "
<< "Profile changes will not be monitored.";
});

property_provider_.events().OnChange = [this]() {
property_provider_->GetProfile(
[this](Profile profile) { on_profile_changed_.Run(profile); });
};
}

IntlProfileWatcher::~IntlProfileWatcher() = default;

// static
std::string IntlProfileWatcher::GetPrimaryTimeZoneIdFromProfile(
const Profile& profile) {
if (!profile.has_time_zones()) {
DLOG(WARNING) << "Profile does not contain time zones.";
return std::string();
}

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.";
return std::string();
}

return time_zones[0].id;
}

// static
std::string IntlProfileWatcher::GetPrimaryTimeZoneIdForIcuInitialization() {
::fuchsia::intl::PropertyProviderSyncPtr provider;
ComponentContextForCurrentProcess()->svc()->Connect(provider.NewRequest());
return GetPrimaryTimeZoneIdFromPropertyProvider(std::move(provider));
}

// static
std::string IntlProfileWatcher::GetPrimaryTimeZoneIdFromPropertyProvider(
::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 GetPrimaryTimeZoneIdFromProfile(profile);
}

} // namespace fuchsia
} // namespace base
63 changes: 63 additions & 0 deletions base/fuchsia/intl_profile_watcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_FUCHSIA_INTL_PROFILE_WATCHER_H_
#define BASE_FUCHSIA_INTL_PROFILE_WATCHER_H_

#include <fuchsia/intl/cpp/fidl.h>
#include <string>

#include "base/base_export.h"
#include "base/callback.h"
#include "base/strings/string_piece_forward.h"

namespace base {
namespace fuchsia {

// Watches fuchsia.intl.PropertyProvider for change notifications and notifies
// the provided callback. If necessary, the caller is responsible for
// determining whether an actual change of interest has occurred.
class BASE_EXPORT IntlProfileWatcher {
public:
using ProfileChangeCallback =
base::RepeatingCallback<void(const ::fuchsia::intl::Profile&)>;

// |on_profile_changed| will be called each time the profile may have changed.
explicit IntlProfileWatcher(ProfileChangeCallback on_profile_changed);

IntlProfileWatcher(const IntlProfileWatcher&) = delete;
IntlProfileWatcher& operator=(const IntlProfileWatcher&) = delete;
~IntlProfileWatcher();

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

// Returns the ID of the primary time zone for the system.
// Returns the empty string if the ID cannot be obtained.
// This is a synchronous blocking call to the system service and should only
// be used for ICU initialization.
static std::string GetPrimaryTimeZoneIdForIcuInitialization();

private:
friend class GetPrimaryTimeZoneIdFromPropertyProviderTest;
friend class IntlProfileWatcherTest;

IntlProfileWatcher(::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(
::fuchsia::intl::PropertyProviderSyncPtr property_provider);

::fuchsia::intl::PropertyProviderPtr property_provider_;
const ProfileChangeCallback on_profile_changed_;
};

} // namespace fuchsia
} // namespace base

#endif // BASE_FUCHSIA_INTL_PROFILE_WATCHER_H_
Loading

0 comments on commit 36d173b

Please sign in to comment.