blob: ac6d256de4b6f56f42b55c19879117d04227c6ec [file] [log] [blame]
// Copyright 2020 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.
package org.chromium.chrome.browser.tasks.tab_management;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.FeatureList;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
import org.chromium.chrome.browser.signin.services.UnifiedConsentServiceBridge;
import org.chromium.chrome.browser.sync.SyncService;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.components.signin.identitymanager.ConsentLevel;
import org.chromium.components.sync.ModelType;
import java.util.concurrent.TimeUnit;
/**
* A class to handle price tracking-related features.
*/
public class PriceTrackingUtilities {
@VisibleForTesting
public static final String PRICE_TRACKING_PARAM = "enable_price_tracking";
@VisibleForTesting
public static final String PRICE_NOTIFICATION_PARAM = "enable_price_notification";
@VisibleForTesting
public static final String ALLOW_DISABLE_PRICE_ANNOTATIONS_PARAM =
"allow_disable_price_annotations";
@VisibleForTesting
public static final String TRACK_PRICES_ON_TABS =
ChromePreferenceKeys.PRICE_TRACKING_TRACK_PRICES_ON_TABS;
@VisibleForTesting
public static final String PRICE_WELCOME_MESSAGE_CARD =
ChromePreferenceKeys.PRICE_TRACKING_PRICE_WELCOME_MESSAGE_CARD;
@VisibleForTesting
public static final String PRICE_WELCOME_MESSAGE_CARD_SHOW_COUNT =
ChromePreferenceKeys.PRICE_TRACKING_PRICE_WELCOME_MESSAGE_CARD_SHOW_COUNT;
@VisibleForTesting
public static final String PRICE_ALERTS_MESSAGE_CARD =
ChromePreferenceKeys.PRICE_TRACKING_PRICE_ALERTS_MESSAGE_CARD;
@VisibleForTesting
public static final String PRICE_ALERTS_MESSAGE_CARD_SHOW_COUNT =
ChromePreferenceKeys.PRICE_TRACKING_PRICE_ALERTS_MESSAGE_CARD_SHOW_COUNT;
private static final String PRICE_ANNOTATIONS_ENABLED_METRICS_WINDOW_DURATION_PARAM =
"price_annotations_enabled_metrics_window_duration_ms";
@VisibleForTesting
public static final SharedPreferencesManager SHARED_PREFERENCES_MANAGER =
SharedPreferencesManager.getInstance();
private static Boolean sIsSignedInAndSyncEnabledForTesting;
/**
* @return whether or not price tracking is enabled.
*/
public static boolean getPriceTrackingEnabled() {
if (FeatureList.isInitialized()) {
return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
ChromeFeatureList.COMMERCE_PRICE_TRACKING, PRICE_TRACKING_PARAM, false);
}
return false;
}
/**
* @return whether or not price tracking notifications are enabled.
*/
public static boolean getPriceTrackingNotificationsEnabled() {
if (FeatureList.isInitialized()) {
return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
ChromeFeatureList.COMMERCE_PRICE_TRACKING, PRICE_NOTIFICATION_PARAM, false);
}
return false;
}
/**
* @return Whether the price tracking feature is eligible to work. Now it is used to determine
* whether the menu item "track prices" is visible and whether the tab has {@link
* TabProperties#SHOPPING_PERSISTED_TAB_DATA_FETCHER}.
*/
public static boolean isPriceTrackingEligible() {
if (sIsSignedInAndSyncEnabledForTesting != null) {
return isPriceTrackingEnabled() && sIsSignedInAndSyncEnabledForTesting;
}
return isPriceTrackingEnabled() && isSignedIn() && isAnonymizedUrlDataCollectionEnabled();
}
/**
* @return Whether the price tracking feature is enabled and available for use.
*/
public static boolean isPriceTrackingEnabled() {
return getPriceTrackingEnabled() || getPriceTrackingNotificationsEnabled();
}
/**
* Update SharedPreferences when users turn on/off the feature tracking prices on tabs.
*/
public static void flipTrackPricesOnTabs() {
final boolean enableTrackPricesOnTabs = SHARED_PREFERENCES_MANAGER.readBoolean(
TRACK_PRICES_ON_TABS, isPriceTrackingEnabled());
SHARED_PREFERENCES_MANAGER.writeBoolean(TRACK_PRICES_ON_TABS, !enableTrackPricesOnTabs);
}
/**
* @return Whether the track prices on tabs is turned on by users.
*/
public static boolean isTrackPricesOnTabsEnabled() {
return isPriceTrackingEligible()
&& SHARED_PREFERENCES_MANAGER.readBoolean(
TRACK_PRICES_ON_TABS, isPriceTrackingEnabled());
}
/**
* Forbid showing the PriceWelcomeMessageCard any more.
*/
public static void disablePriceWelcomeMessageCard() {
SHARED_PREFERENCES_MANAGER.writeBoolean(PRICE_WELCOME_MESSAGE_CARD, false);
}
/**
* @return Whether the PriceWelcomeMessageCard is enabled.
*/
public static boolean isPriceWelcomeMessageCardEnabled() {
return isPriceTrackingEligible()
&& SHARED_PREFERENCES_MANAGER.readBoolean(
PRICE_WELCOME_MESSAGE_CARD, isPriceTrackingEnabled());
}
/**
* Increase the show count of PriceWelcomeMessageCard every time it shows in the tab switcher.
*/
public static void increasePriceWelcomeMessageCardShowCount() {
SHARED_PREFERENCES_MANAGER.writeInt(
PRICE_WELCOME_MESSAGE_CARD_SHOW_COUNT, getPriceWelcomeMessageCardShowCount() + 1);
}
/**
* @return The show count of PriceWelcomeMessageCard.
*/
public static int getPriceWelcomeMessageCardShowCount() {
return SHARED_PREFERENCES_MANAGER.readInt(PRICE_WELCOME_MESSAGE_CARD_SHOW_COUNT, 0);
}
/**
* @return Whether the price drop notification is eligible to work.
*/
public static boolean isPriceDropNotificationEligible() {
return isPriceTrackingEligible() && getPriceTrackingNotificationsEnabled();
}
/**
* Forbid showing the PriceAlertsMessageCard any more.
*/
public static void disablePriceAlertsMessageCard() {
SHARED_PREFERENCES_MANAGER.writeBoolean(PRICE_ALERTS_MESSAGE_CARD, false);
}
/**
* @return Whether the PriceAlertsMessageCard is enabled. We don't show this message card if
* user can already receive price drop notifications, see {@link
* PriceDropNotificationManager#canPostNotification()}.
*/
public static boolean isPriceAlertsMessageCardEnabled() {
return isPriceDropNotificationEligible()
&& SHARED_PREFERENCES_MANAGER.readBoolean(
PRICE_ALERTS_MESSAGE_CARD, isPriceTrackingEnabled())
&& (!(new PriceDropNotificationManager()).canPostNotification());
}
/**
* Increase the show count of PriceAlertsMessageCard every time it shows in the tab switcher.
*/
public static void increasePriceAlertsMessageCardShowCount() {
SHARED_PREFERENCES_MANAGER.writeInt(
PRICE_ALERTS_MESSAGE_CARD_SHOW_COUNT, getPriceAlertsMessageCardShowCount() + 1);
}
/**
* Decrease the show count of PriceAlertsMessageCard. Right now it is used to correct the show
* count when PriceAlertsMessageCard is deprioritized by PriceWelcomeMessageCard.
*/
public static void decreasePriceAlertsMessageCardShowCount() {
SHARED_PREFERENCES_MANAGER.writeInt(
PRICE_ALERTS_MESSAGE_CARD_SHOW_COUNT, getPriceAlertsMessageCardShowCount() - 1);
}
/**
* @return The show count of PriceAlertsMessageCard.
*/
public static int getPriceAlertsMessageCardShowCount() {
return SHARED_PREFERENCES_MANAGER.readInt(PRICE_ALERTS_MESSAGE_CARD_SHOW_COUNT, 0);
}
/**
* @return whether or not the user is in a state that allows them to use price tracking feature.
* Note: These checks can also be used in other commerce features.
*/
public static boolean canFetchCommerceData() {
return isSignedIn() && isOpenTabsSyncEnabled() && isAnonymizedUrlDataCollectionEnabled();
}
private static boolean isSignedIn() {
return IdentityServicesProvider.get()
.getIdentityManager(Profile.getLastUsedRegularProfile())
.hasPrimaryAccount(ConsentLevel.SYNC);
}
private static boolean isOpenTabsSyncEnabled() {
SyncService syncService = SyncService.get();
return syncService != null && syncService.isSyncRequested()
&& syncService.getActiveDataTypes().contains(ModelType.SESSIONS);
}
private static boolean isAnonymizedUrlDataCollectionEnabled() {
return UnifiedConsentServiceBridge.isUrlKeyedAnonymizedDataCollectionEnabled(
Profile.getLastUsedRegularProfile());
}
@VisibleForTesting
public static void setIsSignedInAndSyncEnabledForTesting(Boolean isSignedInAndSyncEnabled) {
sIsSignedInAndSyncEnabledForTesting = isSignedInAndSyncEnabled;
}
/**
* @return if the {@link TabModel} is eligible for price tracking. Not all tab models are - for
* example incognito tabs are not eligible for price tracking.
*/
public static boolean isTabModelPriceTrackingEligible(TabModel tabModel) {
// Incognito Tabs are not eligible for price tracking.
return !tabModel.getProfile().isOffTheRecord();
}
/**
* @return how frequent we want to record metrics on whether user enables the price tracking
* annotations.
*/
public static int getAnnotationsEnabledMetricsWindowDurationMilliSeconds() {
int defaultDuration = (int) TimeUnit.DAYS.toMillis(1);
if (FeatureList.isInitialized()) {
return ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
ChromeFeatureList.COMMERCE_PRICE_TRACKING,
PRICE_ANNOTATIONS_ENABLED_METRICS_WINDOW_DURATION_PARAM, defaultDuration);
}
return defaultDuration;
}
/**
* @return whether we allow users to disable the price annotations feature.
*/
public static boolean allowUsersToDisablePriceAnnotations() {
if (FeatureList.isInitialized()) {
return isPriceTrackingEnabled()
&& ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
ChromeFeatureList.COMMERCE_PRICE_TRACKING,
ALLOW_DISABLE_PRICE_ANNOTATIONS_PARAM, true);
}
return isPriceTrackingEnabled();
}
/**
* @return whether we should show the PriceTrackingSettings menu item in grid tab switcher.
*/
public static boolean shouldShowPriceTrackingMenu() {
return isPriceTrackingEligible()
&& (allowUsersToDisablePriceAnnotations()
|| getPriceTrackingNotificationsEnabled());
}
}