diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java index 7f1806bf20174..2f0dc52d5fc85 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java @@ -109,6 +109,7 @@ import org.chromium.chrome.browser.ui.system.StatusBarColorController.StatusBarColorProvider; import org.chromium.chrome.browser.webapps.AddToHomescreenIPHController; import org.chromium.chrome.browser.webapps.AddToHomescreenMostVisitedTileClickObserver; +import org.chromium.chrome.browser.webapps.PwaRestorePromoUtils; import org.chromium.chrome.features.start_surface.StartSurface; import org.chromium.chrome.features.start_surface.StartSurfaceUserData; import org.chromium.components.browser_ui.accessibility.PageZoomCoordinator; @@ -957,7 +958,17 @@ private boolean triggerPromo(boolean intentWithEffect) { } private boolean maybeShowPromo() { - // Only one promo can be shown in one run to avoid nagging users too much. + // NOTE: Only one promo can be shown in one run to avoid nagging users too much. + + // The PWA Restore promotion runs when we've detected that a user has switched to a new + // device but is leaving behind web apps on the old device. It promotes the idea that the + // user can restore their web apps from their old device (if they have any), and as such it + // is most effective when shown shortly after the first-run experience. It is therefore + // at the front of the list of promotions. + if (PwaRestorePromoUtils.launchPromoIfNeeded( + mActivity, mWindowAndroid, R.drawable.ic_arrow_back_24dp)) { + return true; + } if (FullScreenSyncPromoUtil.launchPromoIfNeeded(mActivity, SyncConsentActivityLauncherImpl.get(), VersionInfo.getProductMajorVersion())) { return true; diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 4263c87806b31..bec81b0940bb5 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc @@ -9853,7 +9853,7 @@ const FeatureEntry kFeatureEntries[] = { {"pwa-restore-ui", flag_descriptions::kPwaRestoreUiName, flag_descriptions::kPwaRestoreUiDescription, kOsAndroid, - FEATURE_VALUE_TYPE(ui::kPwaRestoreUi)}, + FEATURE_VALUE_TYPE(chrome::android::kPwaRestoreUi)}, #endif // BUILDFLAG(IS_ANDROID) {"autofill-enable-ranking-formula-address-profiles", flag_descriptions::kAutofillEnableRankingFormulaAddressProfilesName, diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index a7e99ac28e907..a4907d3382e56 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc @@ -263,6 +263,7 @@ const base::Feature* const kFeaturesExposedToJava[] = { &kPageAnnotationsService, &kPaintPreviewNewColdStartHeuristic, &kPreconnectOnTabCreation, + &kPwaRestoreUi, &kBookmarksImprovedSaveFlow, &kBookmarksRefresh, &kOmahaMinSdkVersionAndroid, @@ -844,6 +845,8 @@ BASE_FEATURE(kPreconnectOnTabCreation, "PreconnectOnTabCreation", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kPwaRestoreUi, "PwaRestoreUi", base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kBookmarksImprovedSaveFlow, "BookmarksImprovedSaveFlow", base::FEATURE_DISABLED_BY_DEFAULT); diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 30a4827f8ab1e..6f6093541d720 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h @@ -137,6 +137,7 @@ BASE_DECLARE_FEATURE(kOptimizeGeolocationHeaderGeneration); BASE_DECLARE_FEATURE(kPageAnnotationsService); BASE_DECLARE_FEATURE(kPaintPreviewNewColdStartHeuristic); BASE_DECLARE_FEATURE(kPreconnectOnTabCreation); +BASE_DECLARE_FEATURE(kPwaRestoreUi); BASE_DECLARE_FEATURE(kBookmarksImprovedSaveFlow); BASE_DECLARE_FEATURE(kBookmarksRefresh); BASE_DECLARE_FEATURE(kPartnerCustomizationsUma); diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 640b9562abaff..09ff31c94f4d7 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java @@ -378,6 +378,7 @@ public static Map getFieldTrialParamsForFeature(String featureNa public static final String PUSH_MESSAGING_DISALLOW_SENDER_IDS = "PushMessagingDisallowSenderIDs"; public static final String PWA_UPDATE_DIALOG_FOR_ICON = "PwaUpdateDialogForIcon"; + public static final String PWA_RESTORE_UI = "PwaRestoreUi"; public static final String QUERY_TILES = "QueryTiles"; public static final String QUERY_TILES_IN_NTP = "QueryTilesInNTP"; public static final String QUERY_TILES_ON_START = "QueryTilesOnStart"; diff --git a/chrome/browser/webapps/android/BUILD.gn b/chrome/browser/webapps/android/BUILD.gn index 00463726ea916..8057a53646355 100644 --- a/chrome/browser/webapps/android/BUILD.gn +++ b/chrome/browser/webapps/android/BUILD.gn @@ -8,7 +8,10 @@ import("//build/config/android/rules.gni") android_library("java") { resources_package = "org.chromium.chrome.browser.webapps" - sources = [ "java/src/org/chromium/chrome/browser/webapps/AddToHomescreenIPHController.java" ] + sources = [ + "java/src/org/chromium/chrome/browser/webapps/AddToHomescreenIPHController.java", + "java/src/org/chromium/chrome/browser/webapps/PwaRestorePromoUtils.java", + ] deps = [ "//base:base_java", @@ -19,6 +22,7 @@ android_library("java") { "//chrome/browser/ui/android/appmenu:java", "//chrome/browser/ui/android/strings:ui_strings_grd", "//chrome/browser/user_education:java", + "//components/browser_ui/bottomsheet/android:java", "//components/browser_ui/styles/android:java_resources", "//components/browser_ui/util/android:java", "//components/embedder_support/android:util_java", diff --git a/chrome/browser/webapps/android/java/src/org/chromium/chrome/browser/webapps/PwaRestorePromoUtils.java b/chrome/browser/webapps/android/java/src/org/chromium/chrome/browser/webapps/PwaRestorePromoUtils.java new file mode 100644 index 0000000000000..55f94d7b182a0 --- /dev/null +++ b/chrome/browser/webapps/android/java/src/org/chromium/chrome/browser/webapps/PwaRestorePromoUtils.java @@ -0,0 +1,50 @@ +// Copyright 2023 The Chromium Authors +// 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.webapps; + +import android.app.Activity; + +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider; +import org.chromium.components.webapps.pwa_restore_ui.PwaRestoreBottomSheetCoordinator; +import org.chromium.ui.base.WindowAndroid; + +/** + * This class is responsible for coordinating the showing of the PWA Restore promo (which aims to + * remind users that they had PWAs installed on their old device, and can restore them on their new + * device. + */ +public class PwaRestorePromoUtils { + /** + * Launch the PWA Restore promotion, if we've determined that this launch meets the criteria for + * for showing it. + * + * @param activity The current {@link Activity} to use for this promo. + * @param windowAndroid The current {@link WindowAndroid} to use for this promo. + * @param arrowResourceId The resource id for the Back arrow to use. + * @return Whether the PWA Restore promo was shown. + */ + public static boolean launchPromoIfNeeded( + Activity activity, WindowAndroid windowAndroid, int arrowResourceId) { + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.PWA_RESTORE_UI)) { + return false; + } + + // TODO(finnur): The criteria for this needs to be fleshed out, but the flag above is + // disabled by default, so we can just attempt to show the dialog for now (which also helps + // during development). + return launchPromo(activity, windowAndroid, arrowResourceId); + } + + private static boolean launchPromo( + Activity activity, WindowAndroid windowAndroid, int arrowResourceId) { + BottomSheetController controller = BottomSheetControllerProvider.from(windowAndroid); + if (controller == null) return false; + PwaRestoreBottomSheetCoordinator pwaRestoreBottomSheetCoordinator = + new PwaRestoreBottomSheetCoordinator(activity, controller, arrowResourceId); + return pwaRestoreBottomSheetCoordinator != null && pwaRestoreBottomSheetCoordinator.show(); + } +} diff --git a/ui/android/ui_android_feature_map.cc b/ui/android/ui_android_feature_map.cc index 9aa71fd71a033..ae4109c1b66f1 100644 --- a/ui/android/ui_android_feature_map.cc +++ b/ui/android/ui_android_feature_map.cc @@ -16,7 +16,6 @@ namespace { const base::Feature* const kFeaturesExposedToJava[] = { &ui::kConvertTrackpadEventsToMouse, &ui::kDeprecatedExternalPickerFunction, - &ui::kPwaRestoreUi, &ui::kReportAllAvailablePointerTypes, }; diff --git a/ui/android/ui_android_features.cc b/ui/android/ui_android_features.cc index e3fa7877ec76c..cc6d07942a4d1 100644 --- a/ui/android/ui_android_features.cc +++ b/ui/android/ui_android_features.cc @@ -17,8 +17,6 @@ BASE_FEATURE(kDeprecatedExternalPickerFunction, "DeprecatedExternalPickerFunction", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kPwaRestoreUi, "PwaRestoreUi", base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kReportAllAvailablePointerTypes, "ReportAllAvailablePointerTypes", base::FEATURE_ENABLED_BY_DEFAULT); diff --git a/ui/android/ui_android_features.h b/ui/android/ui_android_features.h index afe707fea768e..acfc655f970c6 100644 --- a/ui/android/ui_android_features.h +++ b/ui/android/ui_android_features.h @@ -25,9 +25,6 @@ UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kConvertTrackpadEventsToMouse); // Use the old-style opening of an External Picker when uploading files. UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kDeprecatedExternalPickerFunction); -// Enable the PWA Restore functionality. -UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kPwaRestoreUi); - // Reports all of the available pointer types (i.e. coarse, fine) to content // rather than just the first one detected. UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kReportAllAvailablePointerTypes);