chromium/ios/chrome/browser/app_store_rating/ui_bundled/app_store_rating_scene_agent.mm

// Copyright 2022 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/app_store_rating/ui_bundled/app_store_rating_scene_agent.h"

#import "base/metrics/histogram_functions.h"
#import "base/ranges/algorithm.h"
#import "components/password_manager/core/browser/password_manager_util.h"
#import "components/prefs/pref_service.h"
#import "components/variations/service/variations_service.h"
#import "ios/chrome/browser/app_store_rating/ui_bundled/features.h"
#import "ios/chrome/browser/default_browser/model/utils.h"
#import "ios/chrome/browser/promos_manager/model/constants.h"
#import "ios/chrome/browser/promos_manager/model/promos_manager.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_provider.h"
#import "ios/chrome/browser/shared/model/browser/browser_provider_interface.h"
#import "ios/chrome/browser/shared/model/prefs/pref_names.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"

@interface AppStoreRatingSceneAgent ()

// The PromosManager is used to register promos.
@property(nonatomic, assign) PromosManager* promosManager;

@end

@implementation AppStoreRatingSceneAgent

- (instancetype)initWithPromosManager:(PromosManager*)promosManager {
  if ((self = [super init])) {
    _promosManager = promosManager;
  }
  return self;
}

#pragma mark - SceneStateObserver

- (void)sceneState:(SceneState*)sceneState
    transitionedToActivationLevel:(SceneActivationLevel)level {
  if (level == SceneActivationLevelForegroundActive) {
    BOOL isUserEngaged = [self isUserEngaged];
    base::UmaHistogramBoolean("IOS.AppStoreRating.UserIsEligible",
                              isUserEngaged);
    if (isUserEngaged) {
      [self requestPromoDisplay];
    }
  }
}

#pragma mark - Private

// Returns true if the Credentials Provider Extension is enabled.
- (BOOL)isCredentialsProviderConditionMet {
  DCHECK(self.sceneState.browserProviderInterface.mainBrowserProvider.browser);
  PrefService* pref_service =
      self.sceneState.browserProviderInterface.mainBrowserProvider.browser
          ->GetBrowserState()
          ->GetPrefs();
  return password_manager_util::IsCredentialProviderEnabledOnStartup(
      pref_service);
}

// Returns true if this is likely the user's default browser and the user is not
// in a country excluded from the default browser eligibility condition.
- (BOOL)isDefaultBrowserConditionMet {
  // If for some reason the variations service isn't available to determine the
  // current country, err on the side of caution and assume the country is
  // excluded.
  BOOL countryIsExcluded = true;
  variations::VariationsService* variations_service =
      GetApplicationContext()->GetVariationsService();
  if (variations_service) {
    countryIsExcluded =
        base::Contains(GetCountriesExcludedFromDefaultBrowserCondition(),
                       variations_service->GetStoredPermanentCountry());
  }
  return IsChromeLikelyDefaultBrowser() && !countryIsExcluded;
}

// Returns true if the user is considered engaged for the purpose of the App
// Store rating prompt. A user is considered engaged if they satisfy either the
// default browser or the Credentials Provider Extension condition.
- (BOOL)isUserEngaged {
  return [self isDefaultBrowserConditionMet] ||
         [self isCredentialsProviderConditionMet];
}

// Registers the App Store rating prompt with the promo manager.
- (void)requestPromoDisplay {
  if (!_promosManager || !GetApplicationContext()->GetLocalState()->GetBoolean(
                             prefs::kAppStoreRatingPolicyEnabled)) {
    return;
  }
  _promosManager->RegisterPromoForSingleDisplay(
      promos_manager::Promo::AppStoreRating);
}

@end