Commit defb8277 authored by Wenyu Fu's avatar Wenyu Fu Committed by Commit Bot

[HomepagePromo] Add two finch flags for homepage promo experiment

Add two finch flags to collect synthetic trial data for enable/tracking-
only group that users has "seen" the homepage promo.

Bug: 1068831, 1084292
Change-Id: Ibf798c0f814c215fd958af2e9463828358b23be2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2208271
Commit-Queue: Wenyu Fu <wenyufu@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#773382}
parent 1b881dab
......@@ -138,6 +138,7 @@ chrome_junit_test_java_sources = [
"junit/src/org/chromium/chrome/browser/ntp/TitleUtilTest.java",
"junit/src/org/chromium/chrome/browser/ntp/cards/InnerNodeTest.java",
"junit/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoUnitTest.java",
"junit/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoVariationManagerTest.java",
"junit/src/org/chromium/chrome/browser/offlinepages/BackgroundSchedulerTest.java",
"junit/src/org/chromium/chrome/browser/offlinepages/CctOfflinePageModelObserverTest.java",
"junit/src/org/chromium/chrome/browser/offlinepages/ClientIdTest.java",
......
......@@ -106,6 +106,7 @@ import org.chromium.chrome.browser.navigation_predictor.NavigationPredictorBridg
import org.chromium.chrome.browser.night_mode.WebContentsDarkModeController;
import org.chromium.chrome.browser.ntp.NewTabPage;
import org.chromium.chrome.browser.ntp.NewTabPageUma;
import org.chromium.chrome.browser.ntp.cards.promo.HomepagePromoVariationManager;
import org.chromium.chrome.browser.omaha.OmahaBase;
import org.chromium.chrome.browser.omnibox.LocationBar;
import org.chromium.chrome.browser.paint_preview.PaintPreviewTabHelper;
......@@ -1677,6 +1678,8 @@ public class ChromeTabbedActivity extends ChromeActivity<ChromeActivityComponent
LauncherShortcutActivity.updateIncognitoShortcut(ChromeTabbedActivity.this);
ChromeSurveyController.initialize(mTabModelSelectorImpl);
HomepagePromoVariationManager.getInstance().tagSyntheticHomepagePromoSeenGroup();
});
}
......
......@@ -7,8 +7,13 @@ package org.chromium.chrome.browser.ntp.cards.promo;
import androidx.annotation.StringDef;
import androidx.annotation.VisibleForTesting;
import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.metrics.UmaSessionStats;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.components.browser_ui.widget.promo.PromoCardCoordinator.LayoutStyle;
import org.chromium.components.feature_engagement.FeatureConstants;
import org.chromium.components.feature_engagement.Tracker;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
......@@ -26,8 +31,23 @@ public class HomepagePromoVariationManager {
String SLIM = "Slim";
}
// A helper class for Synthetic Field trial helper. Adding to makes test easier.
interface SyntheticTrialHelper {
boolean hasEverTriggered();
void registerSyntheticFieldTrial(String groupName);
boolean isClientInIPHTrackingOnlyGroup();
boolean isClientInEnabledStudyGroup();
boolean isClientInTrackingStudyGroup();
}
private static HomepagePromoVariationManager sInstance;
private SyntheticTrialHelper mStudyHelper;
/**
* @return Singleton instance for {@link HomepagePromoVariationManager}.
*/
......@@ -38,6 +58,43 @@ public class HomepagePromoVariationManager {
return sInstance;
}
private HomepagePromoVariationManager() {
mStudyHelper = new SyntheticTrialHelper() {
@Override
public boolean hasEverTriggered() {
Tracker tracker =
TrackerFactory.getTrackerForProfile(Profile.getLastUsedRegularProfile());
return tracker.hasEverTriggered(
FeatureConstants.HOMEPAGE_PROMO_CARD_FEATURE, false);
}
@Override
public void registerSyntheticFieldTrial(String groupName) {
UmaSessionStats.registerSyntheticFieldTrial(
FeatureConstants.HOMEPAGE_PROMO_CARD_FEATURE, groupName);
}
@Override
public boolean isClientInIPHTrackingOnlyGroup() {
return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
FeatureConstants.HOMEPAGE_PROMO_CARD_FEATURE, "tracking-only", false);
}
@Override
public boolean isClientInEnabledStudyGroup() {
return ChromeFeatureList.isEnabled(
ChromeFeatureList.HOMEPAGE_PROMO_SYNTHETIC_PROMO_SEEN_ENABLED);
}
@Override
public boolean isClientInTrackingStudyGroup() {
return ChromeFeatureList.isEnabled(
ChromeFeatureList.HOMEPAGE_PROMO_SYNTHETIC_PROMO_SEEN_TRACKING);
}
};
}
@VisibleForTesting
public static void setInstanceForTesting(HomepagePromoVariationManager mock) {
sInstance = mock;
......@@ -64,4 +121,26 @@ public class HomepagePromoVariationManager {
return LayoutStyle.COMPACT;
}
/**
* If the user has ever seen the homepage promo, add a synthetic tag to the user.
*/
public void tagSyntheticHomepagePromoSeenGroup() {
if (mStudyHelper.hasEverTriggered()) {
boolean isTrackingOnly = mStudyHelper.isClientInIPHTrackingOnlyGroup();
if (!isTrackingOnly && !mStudyHelper.isClientInEnabledStudyGroup()) {
mStudyHelper.registerSyntheticFieldTrial(
ChromeFeatureList.HOMEPAGE_PROMO_SYNTHETIC_PROMO_SEEN_ENABLED);
} else if (isTrackingOnly && !mStudyHelper.isClientInTrackingStudyGroup()) {
mStudyHelper.registerSyntheticFieldTrial(
ChromeFeatureList.HOMEPAGE_PROMO_SYNTHETIC_PROMO_SEEN_TRACKING);
}
}
}
@VisibleForTesting
void setStudyHelperForTests(SyntheticTrialHelper helper) {
mStudyHelper = helper;
}
}
......@@ -126,6 +126,7 @@ public class HomepagePromoTest {
Mockito.when(mTracker.shouldTriggerHelpUI(FeatureConstants.HOMEPAGE_PROMO_CARD_FEATURE))
.thenReturn(true);
TrackerFactory.setTrackerForTests(mTracker);
HomepagePromoVariationManager.setInstanceForTesting(mMockVariationManager);
// By default, use default homepage just like a first time user.
mHomepageTestRule.useDefaultHomepageForTest();
......@@ -361,6 +362,9 @@ public class HomepagePromoTest {
@Test
@SmallTest
public void testExperimentTrackerSignals() {
// Tagging for synthetic trial should happen once.
Mockito.verify(mMockVariationManager, times(1)).tagSyntheticHomepagePromoSeenGroup();
mHomepageTestRule.useChromeNTPForTest();
ToolbarManager toolbarManager = mActivityTestRule.getActivity().getToolbarManager();
......@@ -395,6 +399,5 @@ public class HomepagePromoTest {
private void setVariationForTests(@LayoutStyle int variation) {
Mockito.when(mMockVariationManager.getLayoutVariation()).thenReturn(variation);
HomepagePromoVariationManager.setInstanceForTesting(mMockVariationManager);
}
}
// 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.ntp.cards.promo;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
/**
* Unit test for {@link HomepagePromoVariationManager}.
*/
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class HomepagePromoVariationManagerTest {
private static final String STUDY_ENABLED_GROUP =
ChromeFeatureList.HOMEPAGE_PROMO_SYNTHETIC_PROMO_SEEN_ENABLED;
private static final String STUDY_TRACKING_GROUP =
ChromeFeatureList.HOMEPAGE_PROMO_SYNTHETIC_PROMO_SEEN_TRACKING;
@Mock
public HomepagePromoVariationManager.SyntheticTrialHelper mStudyHelper;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
HomepagePromoVariationManager.getInstance().setStudyHelperForTests(mStudyHelper);
}
@After
public void tearDown() {
Mockito.reset(mStudyHelper);
}
@Test
@SmallTest
public void testStudyEnabled_EnabledGroup() {
setStudyHelper(true, true, false);
HomepagePromoVariationManager.getInstance().tagSyntheticHomepagePromoSeenGroup();
Mockito.verify(mStudyHelper, times(1)).isClientInIPHTrackingOnlyGroup();
Mockito.verify(mStudyHelper, times(1)).isClientInEnabledStudyGroup();
Mockito.verify(mStudyHelper, never()).isClientInTrackingStudyGroup();
Mockito.verify(mStudyHelper, never()).registerSyntheticFieldTrial(anyString());
}
@Test
@SmallTest
public void testStudyEnabled_TrackingGroup() {
setStudyHelper(true, true, true);
HomepagePromoVariationManager.getInstance().tagSyntheticHomepagePromoSeenGroup();
Mockito.verify(mStudyHelper, times(1)).isClientInIPHTrackingOnlyGroup();
Mockito.verify(mStudyHelper, never()).isClientInEnabledStudyGroup();
Mockito.verify(mStudyHelper, times(1)).isClientInTrackingStudyGroup();
Mockito.verify(mStudyHelper, never()).registerSyntheticFieldTrial(anyString());
}
/**
* If study disabled and client in enabled group, STUDY_ENABLED_GROUP should be tagged in
* SyntheticFieldTrial.
*/
@Test
@SmallTest
public void testStudyDisabled_EnabledGroup() {
setStudyHelper(true, false, false);
HomepagePromoVariationManager.getInstance().tagSyntheticHomepagePromoSeenGroup();
Mockito.verify(mStudyHelper, times(1)).isClientInIPHTrackingOnlyGroup();
Mockito.verify(mStudyHelper, times(1)).isClientInEnabledStudyGroup();
Mockito.verify(mStudyHelper, never()).isClientInTrackingStudyGroup();
Mockito.verify(mStudyHelper, times(1)).registerSyntheticFieldTrial(STUDY_ENABLED_GROUP);
Mockito.verify(mStudyHelper, never()).registerSyntheticFieldTrial(STUDY_TRACKING_GROUP);
}
/**
* If study disabled and client in tracking-only, STUDY_TRACKING_GROUP should be tagged in
* SyntheticFieldTrial.
*/
@Test
@SmallTest
public void testStudyDisabled_TrackingGroup() {
setStudyHelper(true, false, true);
HomepagePromoVariationManager.getInstance().tagSyntheticHomepagePromoSeenGroup();
Mockito.verify(mStudyHelper, times(1)).isClientInIPHTrackingOnlyGroup();
Mockito.verify(mStudyHelper, never()).isClientInEnabledStudyGroup();
Mockito.verify(mStudyHelper, times(1)).isClientInTrackingStudyGroup();
Mockito.verify(mStudyHelper, never()).registerSyntheticFieldTrial(STUDY_ENABLED_GROUP);
Mockito.verify(mStudyHelper, times(1)).registerSyntheticFieldTrial(STUDY_TRACKING_GROUP);
}
/**
* If promo has never triggered, none of the study flag should be triggered, and
* registerSyntheticFieldTrial should not happened.
*/
@Test
@SmallTest
public void testNotEverTriggered() {
setStudyHelper(false, true, true);
HomepagePromoVariationManager.getInstance().tagSyntheticHomepagePromoSeenGroup();
Mockito.verify(mStudyHelper, never()).isClientInIPHTrackingOnlyGroup();
Mockito.verify(mStudyHelper, never()).isClientInEnabledStudyGroup();
Mockito.verify(mStudyHelper, never()).isClientInTrackingStudyGroup();
Mockito.verify(mStudyHelper, never()).registerSyntheticFieldTrial(any());
}
private void setStudyHelper(
boolean hasEverTriggered, boolean isStudyEnabled, boolean isInTrackingGroup) {
Mockito.doReturn(hasEverTriggered).when(mStudyHelper).hasEverTriggered();
Mockito.doReturn(isStudyEnabled).when(mStudyHelper).isClientInEnabledStudyGroup();
Mockito.doReturn(isStudyEnabled).when(mStudyHelper).isClientInTrackingStudyGroup();
Mockito.doReturn(isInTrackingGroup).when(mStudyHelper).isClientInIPHTrackingOnlyGroup();
}
}
......@@ -92,6 +92,7 @@ const base::Feature* kFeaturesExposedToJava[] = {
&feature_engagement::kIPHChromeDuetHomeButtonFeature,
&feature_engagement::kIPHChromeDuetSearchFeature,
&feature_engagement::kIPHChromeDuetTabSwitcherFeature,
&feature_engagement::kIPHHomepagePromoCardFeature,
&feed::kInterestFeedContentSuggestions,
&feed::kInterestFeedFeedback,
&feed::kInterestFeedV2,
......@@ -155,6 +156,8 @@ const base::Feature* kFeaturesExposedToJava[] = {
&kHandleMediaIntents,
&kHomepageLocation,
&kHomepagePromoCard,
&kHomepagePromoSyntheticPromoSeenEnabled,
&kHomepagePromoSyntheticPromoSeenTracking,
&kHomepageSettingsUIConversion,
&kHorizontalTabSwitcherAndroid,
&kImmersiveUiMode,
......@@ -450,6 +453,14 @@ const base::Feature kHomepageLocation{"HomepageLocationPolicy",
const base::Feature kHomepagePromoCard{"HomepagePromoCard",
base::FEATURE_DISABLED_BY_DEFAULT};
// Homepage Promo experiment group for synthetic field trial.
const base::Feature kHomepagePromoSyntheticPromoSeenEnabled{
"HomepagePromoSyntheticPromoSeenEnabled",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kHomepagePromoSyntheticPromoSeenTracking{
"HomepagePromoSyntheticPromoSeenTracking",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kHomepageSettingsUIConversion{
"HomepageSettingsUIConversion", base::FEATURE_ENABLED_BY_DEFAULT};
......
......@@ -74,6 +74,8 @@ extern const base::Feature kFocusOmniboxInIncognitoTabIntents;
extern const base::Feature kHandleMediaIntents;
extern const base::Feature kHomepageLocation;
extern const base::Feature kHomepagePromoCard;
extern const base::Feature kHomepagePromoSyntheticPromoSeenEnabled;
extern const base::Feature kHomepagePromoSyntheticPromoSeenTracking;
extern const base::Feature kHomepageSettingsUIConversion;
extern const base::Feature kHorizontalTabSwitcherAndroid;
extern const base::Feature kImmersiveUiMode;
......
......@@ -289,6 +289,10 @@ public abstract class ChromeFeatureList {
public static final String HANDLE_MEDIA_INTENTS = "HandleMediaIntents";
public static final String HOMEPAGE_LOCATION_POLICY = "HomepageLocationPolicy";
public static final String HOMEPAGE_PROMO_CARD = "HomepagePromoCard";
public static final String HOMEPAGE_PROMO_SYNTHETIC_PROMO_SEEN_ENABLED =
"HomepagePromoSyntheticPromoSeenEnabled";
public static final String HOMEPAGE_PROMO_SYNTHETIC_PROMO_SEEN_TRACKING =
"HomepagePromoSyntheticPromoSeenTracking";
public static final String HOMEPAGE_SETTINGS_UI_CONVERSION = "HomepageSettingsUIConversion";
public static final String HORIZONTAL_TAB_SWITCHER_ANDROID = "HorizontalTabSwitcherAndroid";
public static final String IMMERSIVE_UI_MODE = "ImmersiveUiMode";
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment