blob: 2e8443c6e9df130c8a797fe3e01b172ceae16f8d [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 <fuchsia/intl/cpp/fidl.h>
#include <fuchsia/intl/merge/cpp/fidl.h>
#include <fuchsia/settings/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fpromise/result.h>
#include <queue>
#include <sdk/lib/sys/cpp/component_context.h>
namespace intl {
// Implementation of `fuchsia.intl.PropertyProvider`.
// Serves an up-to-date `fuchsia.intl.Profile`, based on watched user settings.
// Example use, with types and required includes elided for brevity is below.
// ```
// async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
// auto context = sys::ComponentContext::CreateAndServeOutgoingDirectory();
// // Connects to required backend services through context->svc().
// auto intl = IntlPropertyProviderImpl::Create(context->svc());
// // Starts serving `fuchsia.intl.PropertyProvider`.
// context->outgoing()->AddPublicService(intl->GetHandler());
// // Waits for events in the async loop.
// loop.Run();
// ```
class IntlPropertyProviderImpl final : fuchsia::intl::PropertyProvider {
explicit IntlPropertyProviderImpl(fuchsia::settings::IntlPtr settings_client_);
// Create an instance of `IntlPropertyProviderImpl`, after using the given `ServiceDirectory` to
// connect to all of the provider's service dependencies.
static std::unique_ptr<IntlPropertyProviderImpl> Create(
const std::shared_ptr<sys::ServiceDirectory>& incoming_services);
// Returns the client-side handler for `fuchsia.intl.PropertyProvider`, based on either the
// dispatcher that is passed in (e.g. for testing), or the default thread-local dispatcher.
fidl::InterfaceRequestHandler<fuchsia::intl::PropertyProvider> GetHandler(
async_dispatcher_t* dispatcher = nullptr);
// Start serving the intl profile and listening for user preference changes.
void Start();
// Put the callback in a queue (in case the data is not yet available).
// `fuchsia.intl.PropertyProvider`
void GetProfile(fuchsia::intl::PropertyProvider::GetProfileCallback callback) override;
// Start watching changes in user preferences. Each setting type is watched separately.
void StartSettingsWatcher();
// Load the initial profiles values from user preferences and defaults.
void LoadInitialValues();
// Get a clone of the current `Profile` if available. If the raw data has not yet been
// initialized, returns `ZX_ERR_SHOULD_WAIT`. Other errors are also possible, e.g.
// `ZX_ERR_INVALID_ARGS` if the raw data is invalid or `ZX_ERR_INTERNAL` if various internal
// problems arise.
fpromise::result<fuchsia::intl::Profile, zx_status_t> GetProfileInternal();
// Return true if the initial raw data has been set and is ready to be transformed into a
// `Profile`.
bool IsRawDataInitialized();
// Replace the stored raw data, and, if the data has actually changed, trigger notifications to
// watchers and pending requesters.
bool UpdateRawData(fuchsia::intl::merge::Data new_raw_data);
// Send the Profile to any queued callers of `GetProfile`.
void ProcessProfileRequests();
// A snapshot of the assembled intl `Profile`.
std::optional<fuchsia::intl::Profile> intl_profile_;
// Raw data that will be used to assemble the `Profile`. Initially empty, and remains empty
// until a first successful read result comes in.
std::optional<fuchsia::intl::merge::Data> raw_profile_data_;
fidl::BindingSet<fuchsia::intl::PropertyProvider> property_provider_bindings_;
// The client connecting to the intl service.
fuchsia::settings::IntlPtr settings_client_;
// Queue of pending requests
std::queue<fuchsia::intl::PropertyProvider::GetProfileCallback> get_profile_queue_;
} // namespace intl