Commit c92ce91f authored by Finnur Thorarinsson's avatar Finnur Thorarinsson Committed by Commit Bot

[Android] Add In-product help for PWA install menu.

Bug: 1135551
Change-Id: If6eb558fd23c74b16479a4f23b4327b522a828e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2442691Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarPeter Conn <peconn@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Commit-Queue: Finnur Thorarinsson <finnur@chromium.org>
Cr-Commit-Position: refs/heads/master@{#816216}
parent a2ff39d1
...@@ -138,6 +138,9 @@ chrome_java_sources = [ ...@@ -138,6 +138,9 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/background_task_scheduler/ChromeBackgroundTaskFactory.java", "java/src/org/chromium/chrome/browser/background_task_scheduler/ChromeBackgroundTaskFactory.java",
"java/src/org/chromium/chrome/browser/background_task_scheduler/ChromeNativeBackgroundTaskDelegate.java", "java/src/org/chromium/chrome/browser/background_task_scheduler/ChromeNativeBackgroundTaskDelegate.java",
"java/src/org/chromium/chrome/browser/background_task_scheduler/ProxyNativeTask.java", "java/src/org/chromium/chrome/browser/background_task_scheduler/ProxyNativeTask.java",
"java/src/org/chromium/chrome/browser/banners/AppBannerInProductHelpController.java",
"java/src/org/chromium/chrome/browser/banners/AppBannerInProductHelpControllerFactory.java",
"java/src/org/chromium/chrome/browser/banners/AppBannerInProductHelpControllerProvider.java",
"java/src/org/chromium/chrome/browser/banners/AppBannerManager.java", "java/src/org/chromium/chrome/browser/banners/AppBannerManager.java",
"java/src/org/chromium/chrome/browser/banners/AppData.java", "java/src/org/chromium/chrome/browser/banners/AppData.java",
"java/src/org/chromium/chrome/browser/banners/AppDetailsDelegate.java", "java/src/org/chromium/chrome/browser/banners/AppDetailsDelegate.java",
......
// 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.banners;
import android.app.Activity;
import android.os.Handler;
import android.view.View;
import org.chromium.base.UnownedUserData;
import org.chromium.base.supplier.Supplier;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler;
import org.chromium.chrome.browser.user_education.IPHCommandBuilder;
import org.chromium.chrome.browser.user_education.UserEducationHelper;
import org.chromium.components.feature_engagement.FeatureConstants;
/**
* This class is responsible for managing the in-product help for the PWA app banners.
*/
public class AppBannerInProductHelpController implements UnownedUserData {
private final Activity mActivity;
private final AppMenuHandler mAppMenuHandler;
private final Supplier<View> mMenuButtonView;
private final Handler mHandler = new Handler();
private final UserEducationHelper mUserEducationHelper;
/**
* Constructs an AppBannerInProductHelpController.
* @param activity The current activity.
* @param appMenuHandler The app menu containing the menu entry to highlight.
* @param menuButtonView The menu button view to anchor the bubble to.
*/
public AppBannerInProductHelpController(
Activity activity, AppMenuHandler appMenuHandler, Supplier<View> menuButtonView) {
mActivity = activity;
mAppMenuHandler = appMenuHandler;
mMenuButtonView = menuButtonView;
mUserEducationHelper =
new UserEducationHelper(mActivity, mHandler, TrackerFactory::getTrackerForProfile);
}
/**
* Makes an asynchronous request to show the in-product help, anchored to app menu.
*/
public void requestInProductHelp() {
IPHCommandBuilder builder = new IPHCommandBuilder(mActivity.getResources(),
FeatureConstants.PWA_INSTALL_AVAILABLE_FEATURE,
R.string.iph_pwa_install_available_text, R.string.iph_pwa_install_available_text);
mUserEducationHelper.requestShowIPH(
builder.setAnchorView(mMenuButtonView.get())
.setOnShowCallback(this::turnOnHighlightForMenu)
.setOnDismissCallback(this::turnOffHighlightForMenu)
.build());
}
private void turnOnHighlightForMenu() {
mAppMenuHandler.setMenuHighlight(R.id.add_to_homescreen_id, true);
}
private void turnOffHighlightForMenu() {
mAppMenuHandler.clearMenuHighlight();
}
}
// 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.banners;
import android.app.Activity;
import android.view.View;
import org.chromium.base.supplier.Supplier;
import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler;
import org.chromium.ui.base.WindowAndroid;
/**
* A factory for producing a {@link AppBannerInProductHelpController}.
*/
public class AppBannerInProductHelpControllerFactory {
public static AppBannerInProductHelpController createAppBannerInProductHelpController(
Activity activity, AppMenuHandler appMenuHandler, Supplier<View> menuButtonView) {
return new AppBannerInProductHelpController(activity, appMenuHandler, menuButtonView);
}
public static void attach(
WindowAndroid windowAndroid, AppBannerInProductHelpController controller) {
AppBannerInProductHelpControllerProvider.attach(windowAndroid, controller);
}
public static void detach(AppBannerInProductHelpController controller) {
AppBannerInProductHelpControllerProvider.detach(controller);
}
}
// 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.banners;
import org.chromium.base.UnownedUserDataKey;
import org.chromium.ui.base.WindowAndroid;
/**
* This class manages the details associated with binding a {@link AppBannerInProductHelpController}
* to user data on a {@link WindowAndroid}.
*/
public class AppBannerInProductHelpControllerProvider {
/** The key used to bind the controller to the unowned data host. */
private static final UnownedUserDataKey<AppBannerInProductHelpController> KEY =
new UnownedUserDataKey<>(AppBannerInProductHelpController.class);
/**
* Get the shared {@link AppBannerInProductHelpController} from the provided {@link
* WindowAndroid}.
* @param windowAndroid The window to pull the controller from.
* @return A shared instance of a {@link AppBannerInProductHelpController}.
*/
public static AppBannerInProductHelpController from(WindowAndroid windowAndroid) {
return KEY.retrieveDataFromHost(windowAndroid.getUnownedUserDataHost());
}
static void attach(WindowAndroid windowAndroid, AppBannerInProductHelpController controller) {
KEY.attachToHost(windowAndroid.getUnownedUserDataHost(), controller);
}
static void detach(AppBannerInProductHelpController controller) {
KEY.detachFromAllHosts(controller);
}
}
...@@ -17,9 +17,14 @@ import org.chromium.base.annotations.JNINamespace; ...@@ -17,9 +17,14 @@ import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ShortcutHelper; import org.chromium.chrome.browser.ShortcutHelper;
import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.vr.VrModuleProvider; import org.chromium.chrome.browser.vr.VrModuleProvider;
import org.chromium.components.feature_engagement.FeatureConstants;
import org.chromium.components.feature_engagement.Tracker;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.WindowAndroid;
/** /**
* Manages an AppBannerInfoBar for a Tab. * Manages an AppBannerInfoBar for a Tab.
...@@ -129,6 +134,31 @@ public class AppBannerManager { ...@@ -129,6 +134,31 @@ public class AppBannerManager {
createAppDetailsObserver(), url, packageName, referrer, iconSizeInPx); createAppDetailsObserver(), url, packageName, referrer, iconSizeInPx);
} }
/**
* Request to show the in-product help for installing a PWA.
* @param webContents The current WebContents.
* @return An error message, if unsuccessful. Blank if the request was made.
*/
@CalledByNative
private String showInProductHelp(WebContents webContents) {
// Consult the tracker to see if the IPH can be shown.
Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.fromWebContents(webContents));
if (!tracker.wouldTriggerHelpUI(FeatureConstants.PWA_INSTALL_AVAILABLE_FEATURE)) {
// Tracker replied that the request to show will not be honored. Return whether the
// limit of how often to show has been exceeded.
return "Trigger state: "
+ tracker.getTriggerState(FeatureConstants.PWA_INSTALL_AVAILABLE_FEATURE);
}
WindowAndroid window = webContents.getTopLevelNativeWindow();
if (window == null) return "No window";
AppBannerInProductHelpController controller =
AppBannerInProductHelpControllerProvider.from(window);
if (controller == null) return "No controller";
controller.requestInProductHelp();
return "";
}
private AppDetailsDelegate.Observer createAppDetailsObserver() { private AppDetailsDelegate.Observer createAppDetailsObserver() {
return new AppDetailsDelegate.Observer() { return new AppDetailsDelegate.Observer() {
/** /**
......
...@@ -19,6 +19,8 @@ import org.chromium.base.supplier.Supplier; ...@@ -19,6 +19,8 @@ import org.chromium.base.supplier.Supplier;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.app.ChromeActivity;
import org.chromium.chrome.browser.banners.AppBannerInProductHelpController;
import org.chromium.chrome.browser.banners.AppBannerInProductHelpControllerFactory;
import org.chromium.chrome.browser.bookmarks.BookmarkBridge; import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
import org.chromium.chrome.browser.browser_controls.BrowserControlsSizer; import org.chromium.chrome.browser.browser_controls.BrowserControlsSizer;
import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTabCoordinator; import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTabCoordinator;
...@@ -77,6 +79,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native ...@@ -77,6 +79,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native
private OfflineIndicatorInProductHelpController mOfflineIndicatorInProductHelpController; private OfflineIndicatorInProductHelpController mOfflineIndicatorInProductHelpController;
private UrlFocusChangeListener mUrlFocusChangeListener; private UrlFocusChangeListener mUrlFocusChangeListener;
private @Nullable ToolbarButtonInProductHelpController mToolbarButtonInProductHelpController; private @Nullable ToolbarButtonInProductHelpController mToolbarButtonInProductHelpController;
private AppBannerInProductHelpController mAppBannerInProductHelpController;
private ObservableSupplier<Boolean> mIntentWithEffect; private ObservableSupplier<Boolean> mIntentWithEffect;
private Callback<Boolean> mIntentWithEffectObserver; private Callback<Boolean> mIntentWithEffectObserver;
private HistoryNavigationCoordinator mHistoryNavigationCoordinator; private HistoryNavigationCoordinator mHistoryNavigationCoordinator;
...@@ -152,6 +155,10 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native ...@@ -152,6 +155,10 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native
mToolbarButtonInProductHelpController.destroy(); mToolbarButtonInProductHelpController.destroy();
} }
if (mAppBannerInProductHelpController != null) {
AppBannerInProductHelpControllerFactory.detach(mAppBannerInProductHelpController);
}
if (mHistoryNavigationCoordinator != null) { if (mHistoryNavigationCoordinator != null) {
mHistoryNavigationCoordinator.destroy(); mHistoryNavigationCoordinator.destroy();
mHistoryNavigationCoordinator = null; mHistoryNavigationCoordinator = null;
...@@ -319,6 +326,13 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native ...@@ -319,6 +326,13 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator implements Native
new OfflineIndicatorInProductHelpController(mActivity, mToolbarManager, new OfflineIndicatorInProductHelpController(mActivity, mToolbarManager,
mAppMenuCoordinator.getAppMenuHandler(), mStatusIndicatorCoordinator); mAppMenuCoordinator.getAppMenuHandler(), mStatusIndicatorCoordinator);
} }
mAppBannerInProductHelpController =
AppBannerInProductHelpControllerFactory.createAppBannerInProductHelpController(
mActivity, mAppMenuCoordinator.getAppMenuHandler(),
() -> mActivity.getToolbarManager().getMenuButtonView());
AppBannerInProductHelpControllerFactory.attach(
mActivity.getWindowAndroid(), mAppBannerInProductHelpController);
} }
private void initStatusIndicatorCoordinator(LayoutManager layoutManager) { private void initStatusIndicatorCoordinator(LayoutManager layoutManager) {
......
...@@ -16,7 +16,10 @@ ...@@ -16,7 +16,10 @@
#include "chrome/browser/banners/app_banner_manager_android.h" #include "chrome/browser/banners/app_banner_manager_android.h"
#include "chrome/browser/banners/app_banner_metrics.h" #include "chrome/browser/banners/app_banner_metrics.h"
#include "chrome/browser/banners/app_banner_settings_helper.h" #include "chrome/browser/banners/app_banner_settings_helper.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/installable/installable_metrics.h" #include "chrome/browser/installable/installable_metrics.h"
#include "components/feature_engagement/public/event_constants.h"
#include "components/feature_engagement/public/tracker.h"
#include "components/url_formatter/elide_url.h" #include "components/url_formatter/elide_url.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "ui/gfx/android/java_bitmap.h" #include "ui/gfx/android/java_bitmap.h"
...@@ -209,6 +212,14 @@ void AddToHomescreenMediator::OnDataAvailable(const ShortcutInfo& info, ...@@ -209,6 +212,14 @@ void AddToHomescreenMediator::OnDataAvailable(const ShortcutInfo& info,
} }
UMA_HISTOGRAM_ENUMERATION("Webapp.AddToHomescreenMediator.AppTypeToMenuEntry", UMA_HISTOGRAM_ENUMERATION("Webapp.AddToHomescreenMediator.AppTypeToMenuEntry",
entry, AppTypeToMenuEntry::kAppTypeFinalEntry); entry, AppTypeToMenuEntry::kAppTypeFinalEntry);
if (is_webapk) {
DVLOG(2) << "Sending event: IPH used for Installing PWA";
feature_engagement::Tracker* tracker =
feature_engagement::TrackerFactory::GetForBrowserContext(
data_fetcher_->web_contents()->GetBrowserContext());
tracker->NotifyEvent(feature_engagement::events::kPwaInstallMenuSelected);
}
} }
void AddToHomescreenMediator::RecordEventForAppMenu( void AddToHomescreenMediator::RecordEventForAppMenu(
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
...@@ -24,10 +25,14 @@ ...@@ -24,10 +25,14 @@
#include "chrome/browser/android/webapps/add_to_homescreen_params.h" #include "chrome/browser/android/webapps/add_to_homescreen_params.h"
#include "chrome/browser/banners/app_banner_metrics.h" #include "chrome/browser/banners/app_banner_metrics.h"
#include "chrome/browser/banners/app_banner_settings_helper.h" #include "chrome/browser/banners/app_banner_settings_helper.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/installable/installable_metrics.h" #include "chrome/browser/installable/installable_metrics.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/channel_info.h" #include "chrome/common/channel_info.h"
#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_features.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/feature_engagement/public/tracker.h"
#include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar.h"
#include "components/infobars/core/infobar_delegate.h" #include "components/infobars/core/infobar_delegate.h"
#include "components/version_info/channel.h" #include "components/version_info/channel.h"
...@@ -44,6 +49,14 @@ namespace { ...@@ -44,6 +49,14 @@ namespace {
constexpr char kPlatformPlay[] = "play"; constexpr char kPlatformPlay[] = "play";
// The key to look up what the minimum engagement score is for showing the
// in-product help.
constexpr char kMinEngagementForIphKey[] = "x_min_engagement_for_iph";
// The key to look up whether the in-product help should replace the toolbar or
// complement it.
constexpr char kIphReplacesToolbar[] = "x_iph_replaces_toolbar";
// Whether to ignore the Chrome channel in QueryNativeApp() for testing. // Whether to ignore the Chrome channel in QueryNativeApp() for testing.
bool gIgnoreChromeChannelForTesting = false; bool gIgnoreChromeChannelForTesting = false;
...@@ -457,7 +470,52 @@ base::string16 AppBannerManagerAndroid::GetAppName() const { ...@@ -457,7 +470,52 @@ base::string16 AppBannerManagerAndroid::GetAppName() const {
return native_app_title_; return native_app_title_;
} }
bool AppBannerManagerAndroid::MaybeShowInProductHelp() const {
if (!web_contents()) {
DVLOG(2) << "IPH for PWA aborted: null WebContents";
return false;
}
Profile* profile =
Profile::FromBrowserContext(web_contents()->GetBrowserContext());
if (!profile) {
DVLOG(2) << "IPH for PWA aborted: unable to obtain profile";
return false;
}
double last_engagement_score =
GetSiteEngagementService()->GetScore(validated_url_);
int min_engagement = base::GetFieldTrialParamByFeatureAsInt(
feature_engagement::kIPHPwaInstallAvailableFeature,
kMinEngagementForIphKey, 0);
if (last_engagement_score < min_engagement) {
DVLOG(2) << "IPH for PWA aborted: Engagement score too low: "
<< last_engagement_score << " < " << min_engagement;
return false;
}
JNIEnv* env = base::android::AttachCurrentThread();
std::string error_message = base::android::ConvertJavaStringToUTF8(
Java_AppBannerManager_showInProductHelp(
env, java_banner_manager_, web_contents()->GetJavaWebContents()));
if (!error_message.empty()) {
DVLOG(2) << "IPH for PWA showing aborted. " << error_message;
return false;
}
DVLOG(2) << "Showing IPH.";
return true;
}
void AppBannerManagerAndroid::MaybeShowAmbientBadge() { void AppBannerManagerAndroid::MaybeShowAmbientBadge() {
if (MaybeShowInProductHelp() &&
base::GetFieldTrialParamByFeatureAsBool(
feature_engagement::kIPHPwaInstallAvailableFeature,
kIphReplacesToolbar, false)) {
DVLOG(2) << "Install infobar overridden by IPH, as per experiment.";
return;
}
if (!base::FeatureList::IsEnabled(features::kInstallableAmbientBadgeInfoBar)) if (!base::FeatureList::IsEnabled(features::kInstallableAmbientBadgeInfoBar))
return; return;
......
...@@ -132,6 +132,11 @@ class AppBannerManagerAndroid ...@@ -132,6 +132,11 @@ class AppBannerManagerAndroid
// Returns the appropriate app name based on whether we have a native/web app. // Returns the appropriate app name based on whether we have a native/web app.
base::string16 GetAppName() const override; base::string16 GetAppName() const override;
// Shows the in-product help if possible and returns true when a request to
// show it was made, but false if conditions (e.g. engagement score) for
// showing where not deemed adequate.
bool MaybeShowInProductHelp() const;
// Hides the ambient badge if it is showing. // Hides the ambient badge if it is showing.
void HideAmbientBadge(); void HideAmbientBadge();
......
...@@ -2165,6 +2165,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p ...@@ -2165,6 +2165,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_NOTIFICATION_WEBAPK_INSTALLED" desc="Indicates that a WebAPK has been successfully added to Home screen."> <message name="IDS_NOTIFICATION_WEBAPK_INSTALLED" desc="Indicates that a WebAPK has been successfully added to Home screen.">
Added to Home screen Added to Home screen
</message> </message>
<message name="IDS_IPH_PWA_INSTALL_AVAILABLE_TEXT" desc="The in-product-help message for PWAs that can be installed to the device.">
Install this app
</message>
<!-- Page info popup --> <!-- Page info popup -->
<message name="IDS_PAGE_INFO_CONNECTION_OFFLINE" desc="Message to display in the page info bubble when viewing and offline page."> <message name="IDS_PAGE_INFO_CONNECTION_OFFLINE" desc="Message to display in the page info bubble when viewing and offline page.">
......
...@@ -41,7 +41,8 @@ import java.lang.annotation.RetentionPolicy; ...@@ -41,7 +41,8 @@ import java.lang.annotation.RetentionPolicy;
FeatureConstants.HOMEPAGE_PROMO_CARD_FEATURE, FeatureConstants.FEED_HEADER_MENU_FEATURE, FeatureConstants.HOMEPAGE_PROMO_CARD_FEATURE, FeatureConstants.FEED_HEADER_MENU_FEATURE,
FeatureConstants.CHROME_REENGAGEMENT_NOTIFICATION_1_FEATURE, FeatureConstants.CHROME_REENGAGEMENT_NOTIFICATION_1_FEATURE,
FeatureConstants.CHROME_REENGAGEMENT_NOTIFICATION_2_FEATURE, FeatureConstants.CHROME_REENGAGEMENT_NOTIFICATION_2_FEATURE,
FeatureConstants.CHROME_REENGAGEMENT_NOTIFICATION_3_FEATURE}) FeatureConstants.CHROME_REENGAGEMENT_NOTIFICATION_3_FEATURE,
FeatureConstants.PWA_INSTALL_AVAILABLE_FEATURE})
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
public @interface FeatureConstants { public @interface FeatureConstants {
String DOWNLOAD_PAGE_FEATURE = "IPH_DownloadPage"; String DOWNLOAD_PAGE_FEATURE = "IPH_DownloadPage";
...@@ -203,4 +204,9 @@ public @interface FeatureConstants { ...@@ -203,4 +204,9 @@ public @interface FeatureConstants {
* An IPH feature to show the third re-engagement notification. * An IPH feature to show the third re-engagement notification.
*/ */
String CHROME_REENGAGEMENT_NOTIFICATION_3_FEATURE = "IPH_ChromeReengagementNotification3"; String CHROME_REENGAGEMENT_NOTIFICATION_3_FEATURE = "IPH_ChromeReengagementNotification3";
/**
* An IPH feature to inform users that installing a PWA is an option.
*/
String PWA_INSTALL_AVAILABLE_FEATURE = "IPH_PwaInstallAvailable";
} }
...@@ -45,6 +45,10 @@ const char kBottomToolbarOpened[] = "bottom_toolbar_opened"; ...@@ -45,6 +45,10 @@ const char kBottomToolbarOpened[] = "bottom_toolbar_opened";
const char kDiscoverFeedLoaded[] = "discover_feed_loaded"; const char kDiscoverFeedLoaded[] = "discover_feed_loaded";
#endif // defined(OS_IOS) #endif // defined(OS_IOS)
#if defined(OS_ANDROID)
const char kPwaInstallMenuSelected[] = "pwa_install_menu_clicked";
#endif // defined(OS_ANDROID)
} // namespace events } // namespace events
} // namespace feature_engagement } // namespace feature_engagement
...@@ -80,6 +80,12 @@ extern const char kBottomToolbarOpened[]; ...@@ -80,6 +80,12 @@ extern const char kBottomToolbarOpened[];
extern const char kDiscoverFeedLoaded[]; extern const char kDiscoverFeedLoaded[];
#endif // defined(OS_IOS) #endif // defined(OS_IOS)
// Android.
#if defined(OS_ANDROID)
// The user has explicitly used the Install menu item under the App Menu.
extern const char kPwaInstallMenuSelected[];
#endif // defined(OS_ANDROID)
} // namespace events } // namespace events
} // namespace feature_engagement } // namespace feature_engagement
......
...@@ -121,6 +121,8 @@ const base::Feature kIPHChromeReengagementNotification2Feature{ ...@@ -121,6 +121,8 @@ const base::Feature kIPHChromeReengagementNotification2Feature{
"IPH_ChromeReengagementNotification2", base::FEATURE_DISABLED_BY_DEFAULT}; "IPH_ChromeReengagementNotification2", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHChromeReengagementNotification3Feature{ const base::Feature kIPHChromeReengagementNotification3Feature{
"IPH_ChromeReengagementNotification3", base::FEATURE_DISABLED_BY_DEFAULT}; "IPH_ChromeReengagementNotification3", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHPwaInstallAvailableFeature{
"IPH_PwaInstallAvailable", base::FEATURE_ENABLED_BY_DEFAULT};
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
#if defined(OS_IOS) #if defined(OS_IOS)
......
...@@ -79,6 +79,7 @@ extern const base::Feature kIPHFeedHeaderMenuFeature; ...@@ -79,6 +79,7 @@ extern const base::Feature kIPHFeedHeaderMenuFeature;
extern const base::Feature kIPHChromeReengagementNotification1Feature; extern const base::Feature kIPHChromeReengagementNotification1Feature;
extern const base::Feature kIPHChromeReengagementNotification2Feature; extern const base::Feature kIPHChromeReengagementNotification2Feature;
extern const base::Feature kIPHChromeReengagementNotification3Feature; extern const base::Feature kIPHChromeReengagementNotification3Feature;
extern const base::Feature kIPHPwaInstallAvailableFeature;
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
#if defined(OS_IOS) #if defined(OS_IOS)
......
...@@ -46,6 +46,7 @@ const base::Feature* const kAllFeatures[] = { ...@@ -46,6 +46,7 @@ const base::Feature* const kAllFeatures[] = {
&kIPHKeyboardAccessoryPasswordFillingFeature, &kIPHKeyboardAccessoryPasswordFillingFeature,
&kIPHKeyboardAccessoryPaymentFillingFeature, &kIPHKeyboardAccessoryPaymentFillingFeature,
&kIPHPreviewsOmniboxUIFeature, &kIPHPreviewsOmniboxUIFeature,
&kIPHPwaInstallAvailableFeature,
&kIPHQuietNotificationPromptsFeature, &kIPHQuietNotificationPromptsFeature,
&kIPHTabGroupsQuicklyComparePagesFeature, &kIPHTabGroupsQuicklyComparePagesFeature,
&kIPHTabGroupsTapToSeeAnotherTabFeature, &kIPHTabGroupsTapToSeeAnotherTabFeature,
......
...@@ -94,6 +94,8 @@ DEFINE_VARIATION_PARAM(kIPHKeyboardAccessoryPasswordFillingFeature, ...@@ -94,6 +94,8 @@ DEFINE_VARIATION_PARAM(kIPHKeyboardAccessoryPasswordFillingFeature,
DEFINE_VARIATION_PARAM(kIPHKeyboardAccessoryPaymentFillingFeature, DEFINE_VARIATION_PARAM(kIPHKeyboardAccessoryPaymentFillingFeature,
"IPH_KeyboardAccessoryPaymentFilling"); "IPH_KeyboardAccessoryPaymentFilling");
DEFINE_VARIATION_PARAM(kIPHPreviewsOmniboxUIFeature, "IPH_PreviewsOmniboxUI"); DEFINE_VARIATION_PARAM(kIPHPreviewsOmniboxUIFeature, "IPH_PreviewsOmniboxUI");
DEFINE_VARIATION_PARAM(kIPHPwaInstallAvailableFeature,
"IPH_PwaInstallAvailableFeature");
DEFINE_VARIATION_PARAM(kIPHQuietNotificationPromptsFeature, DEFINE_VARIATION_PARAM(kIPHQuietNotificationPromptsFeature,
"IPH_QuietNotificationPrompts"); "IPH_QuietNotificationPrompts");
DEFINE_VARIATION_PARAM(kIPHTabGroupsQuicklyComparePagesFeature, DEFINE_VARIATION_PARAM(kIPHTabGroupsQuicklyComparePagesFeature,
...@@ -184,6 +186,7 @@ constexpr flags_ui::FeatureEntry::FeatureVariation ...@@ -184,6 +186,7 @@ constexpr flags_ui::FeatureEntry::FeatureVariation
VARIATION_ENTRY(kIPHKeyboardAccessoryPasswordFillingFeature), VARIATION_ENTRY(kIPHKeyboardAccessoryPasswordFillingFeature),
VARIATION_ENTRY(kIPHKeyboardAccessoryPaymentFillingFeature), VARIATION_ENTRY(kIPHKeyboardAccessoryPaymentFillingFeature),
VARIATION_ENTRY(kIPHPreviewsOmniboxUIFeature), VARIATION_ENTRY(kIPHPreviewsOmniboxUIFeature),
VARIATION_ENTRY(kIPHPwaInstallAvailableFeature),
VARIATION_ENTRY(kIPHQuietNotificationPromptsFeature), VARIATION_ENTRY(kIPHQuietNotificationPromptsFeature),
VARIATION_ENTRY(kIPHTabGroupsQuicklyComparePagesFeature), VARIATION_ENTRY(kIPHTabGroupsQuicklyComparePagesFeature),
VARIATION_ENTRY(kIPHTabGroupsTapToSeeAnotherTabFeature), VARIATION_ENTRY(kIPHTabGroupsTapToSeeAnotherTabFeature),
......
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