chromium/ios/chrome/browser/metrics/model/ios_chrome_metrics_service_client.mm

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "ios/chrome/browser/metrics/model/ios_chrome_metrics_service_client.h"

#import <UIKit/UIKit.h>
#import <stdint.h>

#import <string>
#import <string_view>
#import <utility>
#import <vector>

#import "base/base64.h"
#import "base/check.h"
#import "base/command_line.h"
#import "base/debug/dump_without_crashing.h"
#import "base/files/file_path.h"
#import "base/functional/bind.h"
#import "base/functional/callback.h"
#import "base/metrics/histogram_functions.h"
#import "base/metrics/histogram_macros.h"
#import "base/metrics/persistent_histogram_allocator.h"
#import "base/path_service.h"
#import "base/process/process_metrics.h"
#import "base/rand_util.h"
#import "base/strings/safe_sprintf.h"
#import "base/task/thread_pool.h"
#import "base/threading/platform_thread.h"
#import "components/crash/core/common/crash_key.h"
#import "components/crash/core/common/crash_keys.h"
#import "components/history/core/browser/history_service.h"
#import "components/keyed_service/core/service_access_type.h"
#import "components/metrics/call_stacks/call_stack_profile_metrics_provider.h"
#import "components/metrics/cpu_metrics_provider.h"
#import "components/metrics/demographics/demographic_metrics_provider.h"
#import "components/metrics/drive_metrics_provider.h"
#import "components/metrics/entropy_state_provider.h"
#import "components/metrics/field_trials_provider.h"
#import "components/metrics/metrics_data_validation.h"
#import "components/metrics/metrics_log_uploader.h"
#import "components/metrics/metrics_pref_names.h"
#import "components/metrics/metrics_reporting_default_state.h"
#import "components/metrics/metrics_service.h"
#import "components/metrics/metrics_state_manager.h"
#import "components/metrics/net/cellular_logic_helper.h"
#import "components/metrics/net/net_metrics_log_uploader.h"
#import "components/metrics/net/network_metrics_provider.h"
#import "components/metrics/persistent_histograms.h"
#import "components/metrics/stability_metrics_helper.h"
#import "components/metrics/ui/form_factor_metrics_provider.h"
#import "components/metrics/ui/screen_info_metrics_provider.h"
#import "components/metrics/url_constants.h"
#import "components/metrics/version_utils.h"
#import "components/omnibox/browser/omnibox_metrics_provider.h"
#import "components/prefs/pref_registry_simple.h"
#import "components/prefs/pref_service.h"
#import "components/sync/service/sync_service.h"
#import "components/sync_device_info/device_count_metrics_provider.h"
#import "components/ukm/ukm_service.h"
#import "components/variations/synthetic_trial_registry.h"
#import "components/variations/variations_associated_data.h"
#import "components/version_info/version_info.h"
#import "google_apis/google_api_keys.h"
#import "ios/chrome/browser/history/model/history_service_factory.h"
#import "ios/chrome/browser/metrics/model/demographics_client.h"
#import "ios/chrome/browser/metrics/model/ios_chrome_default_browser_metrics_provider.h"
#import "ios/chrome/browser/metrics/model/ios_chrome_signin_and_sync_status_metrics_provider.h"
#import "ios/chrome/browser/metrics/model/ios_chrome_stability_metrics_provider.h"
#import "ios/chrome/browser/metrics/model/ios_family_link_user_metrics_provider.h"
#import "ios/chrome/browser/metrics/model/ios_feed_activity_metrics_provider.h"
#import "ios/chrome/browser/metrics/model/ios_feed_enabled_metrics_provider.h"
#import "ios/chrome/browser/metrics/model/ios_profile_session_metrics_provider.h"
#import "ios/chrome/browser/metrics/model/ios_push_notifications_metrics_provider.h"
#import "ios/chrome/browser/metrics/model/mobile_session_shutdown_metrics_provider.h"
#import "ios/chrome/browser/shared/model/application_context/application_context.h"
#import "ios/chrome/browser/shared/model/browser/browser.h"
#import "ios/chrome/browser/shared/model/browser/browser_list.h"
#import "ios/chrome/browser/shared/model/browser/browser_list_factory.h"
#import "ios/chrome/browser/shared/model/browser_state/incognito_session_tracker.h"
#import "ios/chrome/browser/shared/model/paths/paths.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "ios/chrome/browser/shared/model/profile/profile_manager_ios.h"
#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
#import "ios/chrome/browser/signin/model/identity_manager_factory.h"
#import "ios/chrome/browser/sync/model/device_info_sync_service_factory.h"
#import "ios/chrome/browser/sync/model/sync_service_factory.h"
#import "ios/chrome/browser/tabs/model/tab_parenting_global_observer.h"
#import "ios/chrome/browser/translate/model/translate_ranker_metrics_provider.h"
#import "ios/chrome/common/channel_info.h"
#import "ios/public/provider/chrome/browser/app_distribution/app_distribution_api.h"
#import "ios/web/public/thread/web_thread.h"
#import "services/network/public/cpp/shared_url_loader_factory.h"

namespace {

// Maximum amount of local storage for storing persistent histograms.
const int kMaxHistogramStorageKiB = 50 << 10;  // 50 MiB

void GetNetworkConnectionTrackerAsync(
    base::OnceCallback<void(network::NetworkConnectionTracker*)> callback) {
  std::move(callback).Run(
      GetApplicationContext()->GetNetworkConnectionTracker());
}

std::unique_ptr<metrics::FileMetricsProvider> CreateFileMetricsProvider(
    bool metrics_reporting_enabled) {
  // Create an object to monitor files of metrics and include them in reports.
  std::unique_ptr<metrics::FileMetricsProvider> file_metrics_provider(
      new metrics::FileMetricsProvider(
          GetApplicationContext()->GetLocalState()));

  base::FilePath user_data_dir;
  if (base::PathService::Get(ios::DIR_USER_DATA, &user_data_dir)) {
    metrics::FileMetricsProvider::Params browser_metrics_params(
        user_data_dir.AppendASCII(kBrowserMetricsName),
        metrics::FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
        metrics::FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE,
        kBrowserMetricsName);
    browser_metrics_params.max_dir_kib = kMaxHistogramStorageKiB;
    browser_metrics_params.filter = base::BindRepeating(
        &IOSChromeMetricsServiceClient::FilterBrowserMetricsFiles);
    file_metrics_provider->RegisterSource(browser_metrics_params,
                                          metrics_reporting_enabled);
  }
  return file_metrics_provider;
}

}  // namespace

// UKM suffix for field trial recording.
const char kUKMFieldTrialSuffix[] = "UKM";

IOSChromeMetricsServiceClient::IOSChromeMetricsServiceClient(
    metrics::MetricsStateManager* state_manager,
    variations::SyntheticTrialRegistry* synthetic_trial_registry)
    : UkmConsentStateObserver(ukm::NoInitialUkmConsentState),
      metrics_state_manager_(state_manager),
      synthetic_trial_registry_(synthetic_trial_registry),
      stability_metrics_provider_(nullptr) {
  RegisterForNotifications();

  // The IncognitoSessionTracker may be null during unit tests.
  if (IncognitoSessionTracker* tracker =
          GetApplicationContext()->GetIncognitoSessionTracker()) {
    // Using base::Unretained(this) is safe since destroying the subscription
    // will invalidate the callback and the subscription is owned by this.
    incognito_session_tracker_subscription_ =
        tracker->RegisterCallback(base::IgnoreArgs<bool>(base::BindRepeating(
            &IOSChromeMetricsServiceClient::UpdateRunningServices,
            base::Unretained(this))));
  }
}

IOSChromeMetricsServiceClient::~IOSChromeMetricsServiceClient() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}

// static
std::unique_ptr<IOSChromeMetricsServiceClient>
IOSChromeMetricsServiceClient::Create(
    metrics::MetricsStateManager* state_manager,
    variations::SyntheticTrialRegistry* synthetic_trial_registry) {
  // Perform two-phase initialization so that `client->metrics_service_` only
  // receives pointers to fully constructed objects.
  std::unique_ptr<IOSChromeMetricsServiceClient> client(
      new IOSChromeMetricsServiceClient(state_manager,
                                        synthetic_trial_registry));
  client->Initialize();

  return client;
}

// static
void IOSChromeMetricsServiceClient::RegisterPrefs(
    PrefRegistrySimple* registry) {
  metrics::MetricsService::RegisterPrefs(registry);
  metrics::StabilityMetricsHelper::RegisterPrefs(registry);
  metrics::FileMetricsProvider::RegisterSourcePrefs(registry,
                                                    kBrowserMetricsName);
  metrics::RegisterMetricsReportingStatePrefs(registry);
  ukm::UkmService::RegisterPrefs(registry);
}

variations::SyntheticTrialRegistry*
IOSChromeMetricsServiceClient::GetSyntheticTrialRegistry() {
  return synthetic_trial_registry_.get();
}

metrics::MetricsService* IOSChromeMetricsServiceClient::GetMetricsService() {
  return metrics_service_.get();
}

ukm::UkmService* IOSChromeMetricsServiceClient::GetUkmService() {
  return ukm_service_.get();
}

void IOSChromeMetricsServiceClient::SetMetricsClientId(
    const std::string& client_id) {
  crash_keys::SetMetricsClientIdFromGUID(client_id);
}

int32_t IOSChromeMetricsServiceClient::GetProduct() {
  return metrics::ChromeUserMetricsExtension::CHROME;
}

std::string IOSChromeMetricsServiceClient::GetApplicationLocale() {
  return GetApplicationContext()->GetApplicationLocale();
}

const network_time::NetworkTimeTracker*
IOSChromeMetricsServiceClient::GetNetworkTimeTracker() {
  return GetApplicationContext()->GetNetworkTimeTracker();
}

bool IOSChromeMetricsServiceClient::GetBrand(std::string* brand_code) {
  brand_code->assign(ios::provider::GetBrandCode());
  return true;
}

metrics::SystemProfileProto::Channel
IOSChromeMetricsServiceClient::GetChannel() {
  return metrics::AsProtobufChannel(::GetChannel());
}

bool IOSChromeMetricsServiceClient::IsExtendedStableChannel() {
  return false;  // Not supported on iOS.
}

std::string IOSChromeMetricsServiceClient::GetVersionString() {
  return metrics::GetVersionString();
}

void IOSChromeMetricsServiceClient::CollectFinalMetricsForLog(
    base::OnceClosure done_callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  collect_final_metrics_done_callback_ = std::move(done_callback);
  CollectFinalHistograms();
}

std::unique_ptr<metrics::MetricsLogUploader>
IOSChromeMetricsServiceClient::CreateUploader(
    const GURL& server_url,
    const GURL& insecure_server_url,
    std::string_view mime_type,
    metrics::MetricsLogUploader::MetricServiceType service_type,
    const metrics::MetricsLogUploader::UploadCallback& on_upload_complete) {
  return std::make_unique<metrics::NetMetricsLogUploader>(
      GetApplicationContext()->GetSharedURLLoaderFactory(), server_url,
      insecure_server_url, mime_type, service_type, on_upload_complete);
}

base::TimeDelta IOSChromeMetricsServiceClient::GetStandardUploadInterval() {
  return metrics::GetUploadInterval(metrics::ShouldUseCellularUploadInterval());
}

void IOSChromeMetricsServiceClient::WebStateDidStartLoading(
    web::WebState* web_state) {
  metrics_service_->OnApplicationNotIdle();
}

void IOSChromeMetricsServiceClient::WebStateDidStopLoading(
    web::WebState* web_state) {
  metrics_service_->OnApplicationNotIdle();
}

void IOSChromeMetricsServiceClient::Initialize() {
  PrefService* local_state = GetApplicationContext()->GetLocalState();

  synthetic_trial_observation_.Observe(synthetic_trial_registry_.get());

  metrics_service_ = std::make_unique<metrics::MetricsService>(
      metrics_state_manager_, this, local_state);
  RegisterMetricsServiceProviders();

  if (IsMetricsReportingForceEnabled() ||
      base::FeatureList::IsEnabled(ukm::kUkmFeature)) {
    ukm_service_ = std::make_unique<ukm::UkmService>(
        local_state, this,
        std::make_unique<metrics::DemographicMetricsProvider>(
            std::make_unique<metrics::DemographicsClient>(),
            metrics::MetricsLogUploader::MetricServiceType::UKM));

    RegisterUKMProviders();
  }
}

void IOSChromeMetricsServiceClient::RegisterMetricsServiceProviders() {
  PrefService* local_state = GetApplicationContext()->GetLocalState();

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<metrics::NetworkMetricsProvider>(
          base::BindRepeating(&GetNetworkConnectionTrackerAsync)));

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<OmniboxMetricsProvider>());

  auto stability_metrics_provider =
      std::make_unique<IOSChromeStabilityMetricsProvider>(local_state);
  stability_metrics_provider_ = stability_metrics_provider.get();
  metrics_service_->RegisterMetricsProvider(
      std::move(stability_metrics_provider));

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<IOSChromeDefaultBrowserMetricsProvider>(
          metrics::MetricsLogUploader::MetricServiceType::UMA));

  // NOTE: metrics_state_manager_->IsMetricsReportingEnabled() returns false
  // during local testing. To test locally, modify
  // MetricsServiceAccessor::IsMetricsReportingEnabled() to return true.
  metrics_service_->RegisterMetricsProvider(CreateFileMetricsProvider(
      metrics_state_manager_->IsMetricsReportingEnabled()));

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<metrics::EntropyStateProvider>(local_state));

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<metrics::FormFactorMetricsProvider>());

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<metrics::ScreenInfoMetricsProvider>());

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<metrics::DriveMetricsProvider>(ios::FILE_LOCAL_STATE));

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<metrics::CallStackProfileMetricsProvider>());

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<IOSChromeSigninAndSyncStatusMetricsProvider>());

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<IOSFamilyLinkUserMetricsProvider>());

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<MobileSessionShutdownMetricsProvider>(
          metrics_service_.get()));

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<syncer::DeviceCountMetricsProvider>(base::BindRepeating(
          &DeviceInfoSyncServiceFactory::GetAllDeviceInfoTrackers)));

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<translate::TranslateRankerMetricsProvider>());

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<metrics::DemographicMetricsProvider>(
          std::make_unique<metrics::DemographicsClient>(),
          metrics::MetricsLogUploader::MetricServiceType::UMA));

  metrics_service_->RegisterMetricsProvider(
      CreateIOSProfileSessionMetricsProvider());

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<IOSFeedActivityMetricsProvider>());

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<IOSFeedEnabledMetricsProvider>());

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<IOSPushNotificationsMetricsProvider>());
}

void IOSChromeMetricsServiceClient::RegisterUKMProviders() {
  ukm_service_->RegisterMetricsProvider(
      std::make_unique<metrics::CPUMetricsProvider>());

  ukm_service_->RegisterMetricsProvider(
      std::make_unique<metrics::FormFactorMetricsProvider>());

  ukm_service_->RegisterMetricsProvider(
      std::make_unique<metrics::ScreenInfoMetricsProvider>());

  ukm_service_->RegisterMetricsProvider(
      std::make_unique<variations::FieldTrialsProvider>(
          synthetic_trial_registry_.get(), kUKMFieldTrialSuffix));

  metrics_service_->RegisterMetricsProvider(
      std::make_unique<IOSChromeDefaultBrowserMetricsProvider>(
          metrics::MetricsLogUploader::MetricServiceType::UKM));
}

void IOSChromeMetricsServiceClient::CollectFinalHistograms() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  task_vm_info task_info_data;
  mach_msg_type_number_t count = sizeof(task_vm_info) / sizeof(natural_t);
  kern_return_t kr =
      task_info(mach_task_self(), TASK_VM_INFO,
                reinterpret_cast<task_info_t>(&task_info_data), &count);
  if (kr == KERN_SUCCESS) {
    mach_vm_size_t footprint_mb = task_info_data.phys_footprint / 1024 / 1024;
    base::UmaHistogramMemoryLargeMB("Memory.Browser.MemoryFootprint",
                                    footprint_mb);
    // The pseudo metric of Memory.Browser.MemoryFootprint. Only used to
    // assess field trial data quality.
    base::UmaHistogramMemoryLargeMB(
        "UMA.Pseudo.Memory.Browser.MemoryFootprint",
        metrics::GetPseudoMetricsSample(
            static_cast<double>(task_info_data.phys_footprint) / 1024 / 1024));

    switch (UIApplication.sharedApplication.applicationState) {
      case UIApplicationStateActive:
        base::UmaHistogramMemoryLargeMB("Memory.Browser.MemoryFootprint.Active",
                                        footprint_mb);
        // According to Apple, apps on iPhone 6 and older devices get terminated
        // by the OS if memory usage crosses 200MB watermark. Obviously this
        // metric will not be recorded with true on iPhone 6 and older devices.
        UMA_HISTOGRAM_BOOLEAN(
            "Memory.Browser.MemoryFootprint.Active.Over200MBWatermark",
            footprint_mb >= 200);
        break;
      case UIApplicationStateInactive:
        base::UmaHistogramMemoryLargeMB(
            "Memory.Browser.MemoryFootprint.Inactive", footprint_mb);
        break;
      case UIApplicationStateBackground:
        base::UmaHistogramMemoryLargeMB(
            "Memory.Browser.MemoryFootprint.Background", footprint_mb);
        break;
    }
  } else {
    // Max kern_return_t is 0x100 = 256, plus trailing null.
    // (https://opensource.apple.com/source/xnu/xnu-792.25.20/osfmk/mach/kern_return.h)
    // TODO(crbug.com/40866217): Remove this when done debugging the uncaught
    // memory regression.
    static crash_reporter::CrashKeyString<4> task_info_kern_return(
        "task-info-kern-return");
    char kr_buf[4];
    base::strings::SafeSPrintf(kr_buf, "%d", kr);
    task_info_kern_return.Set(kr_buf);
    base::debug::DumpWithoutCrashing();
  }

  int open_tabs_count = 0;
  for (ChromeBrowserState* browser_state :
       GetApplicationContext()->GetProfileManager()->GetLoadedProfiles()) {
    // Iterate through regular Browser and OTR Browser to find the corresponding
    // tab.
    BrowserList* browser_list =
        BrowserListFactory::GetForBrowserState(browser_state);
    std::set<Browser*> browsers =
        browser_list->BrowsersOfType(BrowserList::BrowserType::kAll);

    for (Browser* browser : browsers) {
      open_tabs_count += browser->GetWebStateList()->count();
    }
  }
  base::UmaHistogramCounts10000("Memory.Browser.MemoryFootprint.NumOpenTabs",
                                open_tabs_count);

  std::move(collect_final_metrics_done_callback_).Run();
}

void IOSChromeMetricsServiceClient::RegisterForNotifications() {
  tab_parented_subscription_ =
      TabParentingGlobalObserver::GetInstance()->RegisterCallback(
          base::BindRepeating(&IOSChromeMetricsServiceClient::OnTabParented,
                              base::Unretained(this)));
  omnibox_url_opened_subscription_ =
      OmniboxEventGlobalTracker::GetInstance()->RegisterCallback(
          base::BindRepeating(
              &IOSChromeMetricsServiceClient::OnURLOpenedFromOmnibox,
              base::Unretained(this)));

  // ProfileManagerIOS invoke OnProfileLoaded(...) for all Profiles already
  // loaded, so there is no need to manually iterate over them.
  profile_manager_observation_.Observe(
      GetApplicationContext()->GetProfileManager());
}

bool IOSChromeMetricsServiceClient::RegisterForProfileEvents(
    ChromeBrowserState* profile) {
  history::HistoryService* history_service =
      ios::HistoryServiceFactory::GetForBrowserState(
          profile, ServiceAccessType::IMPLICIT_ACCESS);
  ObserveServiceForDeletions(history_service);
  syncer::SyncService* sync =
      SyncServiceFactory::GetInstance()->GetForBrowserState(profile);
  StartObserving(sync, profile->GetPrefs());
  return (history_service != nullptr && sync != nullptr);
}

void IOSChromeMetricsServiceClient::OnTabParented(web::WebState* web_state) {
  metrics_service_->OnApplicationNotIdle();
}

void IOSChromeMetricsServiceClient::OnURLOpenedFromOmnibox(OmniboxLog* log) {
  metrics_service_->OnApplicationNotIdle();
}

// static
metrics::FileMetricsProvider::FilterAction
IOSChromeMetricsServiceClient::FilterBrowserMetricsFiles(
    const base::FilePath& path) {
  // Do not process the file if it corresponds to the current process id.
  base::ProcessId pid;
  bool parse_success = base::GlobalHistogramAllocator::ParseFilePath(
      path, nullptr, nullptr, &pid);
  if (!parse_success)
    return metrics::FileMetricsProvider::FILTER_PROCESS_FILE;
  if (pid == base::GetCurrentProcId())
    return metrics::FileMetricsProvider::FILTER_ACTIVE_THIS_PID;
  // No need to test whether `pid` is a different active process. This isn't
  // applicable to iOS because there cannot be two copies of Chrome running.
  return metrics::FileMetricsProvider::FILTER_PROCESS_FILE;
}

metrics::EnableMetricsDefault
IOSChromeMetricsServiceClient::GetMetricsReportingDefaultState() {
  return metrics::GetMetricsReportingDefaultState(
      GetApplicationContext()->GetLocalState());
}

void IOSChromeMetricsServiceClient::OnHistoryDeleted() {
  if (ukm_service_)
    ukm_service_->Purge();
}

void IOSChromeMetricsServiceClient::OnUkmAllowedStateChanged(
    bool must_purge,
    ukm::UkmConsentState previous_consent_state) {
  const ukm::UkmConsentState consent_state = GetUkmConsentState();
  if (!ukm_service_)
    return;
  if (must_purge) {
    ukm_service_->Purge();
    ukm_service_->ResetClientState(ukm::ResetReason::kOnUkmAllowedStateChanged);
  } else {
    // Purge recording if required consent has been revoked.
    if (!consent_state.Has(ukm::MSBB)) {
      ukm_service_->PurgeMsbbData();
    }
    // No need to test for ukm::APPS and ukm::EXTENSIONS as they are not
    // supported on iOS.
  }

  // Notify the recording service of changed metrics consent.
  ukm_service_->UpdateRecording(consent_state);

  // Broadcast UKM consent state change.
  ukm_service_->OnUkmAllowedStateChanged(consent_state);

  // Signal service manager to enable/disable UKM based on new state.
  UpdateRunningServices();
}

void IOSChromeMetricsServiceClient::OnProfileManagerDestroyed(
    ProfileManagerIOS* manager) {
  profile_manager_observation_.Reset();
}

void IOSChromeMetricsServiceClient::OnProfileCreated(
    ProfileManagerIOS* manager,
    ChromeBrowserState* profile) {
  // Nothing to do, the Profile is not fully loaded, and it is not possible to
  // access the KeyedService yet.
}

void IOSChromeMetricsServiceClient::OnProfileLoaded(
    ProfileManagerIOS* manager,
    ChromeBrowserState* profile) {
  if (!RegisterForProfileEvents(profile)) {
    notification_listeners_active_ = false;
  }
}

bool IOSChromeMetricsServiceClient::IsUkmAllowedForAllProfiles() {
  return UkmConsentStateObserver::IsUkmAllowedForAllProfiles();
}

bool IOSChromeMetricsServiceClient::
    AreNotificationListenersEnabledOnAllProfiles() {
  return notification_listeners_active_;
}

std::string IOSChromeMetricsServiceClient::GetUploadSigningKey() {
  std::string decoded_key;
  base::Base64Decode(google_apis::GetMetricsKey(), &decoded_key);
  return decoded_key;
}