[User Education] Add Per-App and Critical Notice IPH Modes

This CL adds a "promo subtype" to IPH which allows two new modes which can be applied to most IPH types:
 - Per-App: This IPH can show once per App or PWA, and will not be
   shown for that app once it is completed or dismissed.
 - Legal Notice: This IPH can show any number of times until it is
   dismissed; furthermore it takes precedence over any
   non-legal-notice IPH (but not the legacy critical promos, or other
   legal messaging). It does not show again once dismissed.

Certain types of IPH are not supported in these modes; specifically:
 - Legacy (because nobody should be creating new legacy promos)
 - Snooze (because the behavior is incompatible); note that other
   IPH which would be snoozable now only have the "show me how" and
   "got it" options.

In addition to adding these modes and a large number of tests to ensure they work correctly, this CL also adds auto-configuration and configuration consistency checks for these new promo subtypes.

These promos are still constrained by their Feature Engagement (FE) configuration, but the allowed FE configurations are much broader.

This CL also rearchitects some of the internals of FeaturePromoControllerCommon and FeaturePromoSnoozeService to offload specific IPH lifecycle tracking onto a new FeaturePromoLifecycle class. It also renames the stripped down snooze service to FeaturePromoStorageService, as it now stores all non-transient state information not already handled by feature_engagement::Tracker. These architectural changes not only enable the new behaviors, but also simplify the code and make the business logic much easier to read and understand.

Future work:
 - Determine if we need a combination of the Per-App and Legal Notice subtype.
 - Determine if we need a dismissal that times out (e.g. for a legal notice that must be shown once per year).

Note: Legal notices could theoretically be implemented via extremely specific FE configuration using unlimited trigger and limited used events, with the used event coming from certain kinds of bubble dismissal. However, this would force FE auto-configuration and make Finch much harder; instead I opted to use the existing snooze machinery.

Bug: 1479993, 1479773, 1482527

Change-Id: I498874c12eb41bea58c46e89416583380c3066c8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4855259
Commit-Queue: Dana Fried <[email protected]>
Reviewed-by: Mickey Burks <[email protected]>
Reviewed-by: Tommy Nyquist <[email protected]>
Code-Coverage: [email protected] <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1197988}
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index f36a367..3efc2e8 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -85,7 +85,7 @@
 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
 #include "chrome/browser/ui/toolbar/chrome_labs_prefs.h"
 #include "chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h"
-#include "chrome/browser/ui/user_education/browser_feature_promo_snooze_service.h"
+#include "chrome/browser/ui/user_education/browser_feature_promo_storage_service.h"
 #include "chrome/browser/ui/webui/bookmarks/bookmark_prefs.h"
 #include "chrome/browser/ui/webui/flags/flags_ui.h"
 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
@@ -1717,7 +1717,7 @@
 #else  // BUILDFLAG(IS_ANDROID)
   bookmarks_webui::RegisterProfilePrefs(registry);
   browser_sync::ForeignSessionHandler::RegisterProfilePrefs(registry);
-  BrowserFeaturePromoSnoozeService::RegisterProfilePrefs(registry);
+  BrowserFeaturePromoStorageService::RegisterProfilePrefs(registry);
   captions::LiveTranslateController::RegisterProfilePrefs(registry);
   ChromeAuthenticatorRequestDelegate::RegisterProfilePrefs(registry);
   companion::PromoHandler::RegisterProfilePrefs(registry);