Skip to content

Commit

Permalink
[Password Manager] Add all possible promo dialogs for MVP
Browse files Browse the repository at this point in the history
This CL adds 4 promo cards implementations. For password checkup(shown only if there are saved passwords), managing passwords on
passwords.google.com (shown only if password syncing is enabled), for
creating a shortcut (shown only if shortcut was not created before) and
for how to use Password Manager on Android and iOS.

Promo dialogs shares the same behaviour as bubbles in regards that they
are never shown again if the user explicitly dismissed them or if they
have been shown for 3 times already. The only exception is Password
Checkup promo card which should be shown regularly.

See more: https://docs.google.com/document/d/1MW-54YAiy1osHqWwZlX4QG3GusTCZsiAIZCjuNj963Y/edit#

Bug: 1423346
Change-Id: I6ddbfee8613d8dd43fa9ba308953397a098696d6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4334456
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Mohamed Amir Yosef <mamir@chromium.org>
Commit-Queue: Viktor Semeniuk <vsemeniuk@google.com>
Cr-Commit-Position: refs/heads/main@{#1119848}
  • Loading branch information
Viktor Semeniuk authored and Chromium LUCI CQ committed Mar 21, 2023
1 parent 7b4709d commit 1595e16
Show file tree
Hide file tree
Showing 15 changed files with 639 additions and 20 deletions.
27 changes: 27 additions & 0 deletions chrome/app/password_manager_ui_strings.grdp
Original file line number Diff line number Diff line change
Expand Up @@ -367,4 +367,31 @@
<message name="IDS_PASSWORD_MANAGER_UI_EMPTY_STATE" desc="A label shown if there are no saved passwords prompting user to import them.">
Saved passwords will appear here. &lt;a target='_blank' href='chrome://password-manager/'&gt;Import passwords&lt;/a&gt;
</message>
<message name="IDS_PASSWORD_MANAGER_UI_CHECKUP_PROMO_CARD_TITLE" desc="Title for the Password Checkup promo card.">
Password Checkup
</message>
<message name="IDS_PASSWORD_MANAGER_UI_CHECKUP_PROMO_CARD_DESCRIPTION" desc="Description for the Password Checkup promo card.">
Check your saved passwords to strengthen your security and stay safer online
</message>
<message name="IDS_PASSWORD_MANAGER_UI_CHECKUP_PROMO_CARD_ACTION" desc="Action button for the Password Checkup promo card.">
Check passwords
</message>
<message name="IDS_PASSWORD_MANAGER_UI_WEB_PROMO_CARD_TITLE" desc="Title for the Password Manager on the web promo card.">
Google Password Manger on the web
</message>
<message name="IDS_PASSWORD_MANAGER_UI_WEB_PROMO_CARD_DESCRIPTION" desc="Description for the Password Manager on the web promo card.">
View your passwords even when you're not using Chrome or Android by signing in to &lt;a target='_blank' href='<ph name="LINK">$1</ph>'&gt;passwords.google.com&lt;/a&gt;
</message>
<message name="IDS_PASSWORD_MANAGER_UI_SHORTCUT_PROMO_CARD_TITLE" desc="Title for the Password Manager shortcut promo card.">
Get here quicker
</message>
<message name="IDS_PASSWORD_MANAGER_UI_SHORTCUT_PROMO_CARD_DESCRIPTION" desc="Description for the Password Manager shortcut promo card.">
Add a shortcut to <ph name="BRAND">$1<ex>Google Password Manager</ex></ph>
</message>
<message name="IDS_PASSWORD_MANAGER_UI_ANY_DEVICE_PROMO_CARD_TITLE" desc="Title to encorage users to use password manager on android and iOSss.">
Use saved passwords on any device
</message>
<message name="IDS_PASSWORD_MANAGER_UI_ANY_DEVICE_PROMO_CARD_DESCRIPTION" desc="Description to encorage users to use password manager on android and iOS">
Learn how to get started on &lt;a target='_blank' href='<ph name="LINK_ANDROID">$1</ph>'&gt;Android&lt;/a&gt; and &lt;a target='_blank' href='<ph name="LINK_IOS">$2</ph>'&gt;iOS&lt;/a&gt;
</message>
</grit-part>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
16c190fb9a5a097594830e096cd021d8e861edb7
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
16c190fb9a5a097594830e096cd021d8e861edb7
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2cc2616cbd8fef4e36520ff88d05b36bdc7640fb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2cc2616cbd8fef4e36520ff88d05b36bdc7640fb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2cc2616cbd8fef4e36520ff88d05b36bdc7640fb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
7350bf5147725b786f75193a89de6bcb4d8f0c60
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
7350bf5147725b786f75193a89de6bcb4d8f0c60
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
32a40d9c3b823c8d6dc9688541d9af53c62d7809
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
32a40d9c3b823c8d6dc9688541d9af53c62d7809
13 changes: 8 additions & 5 deletions chrome/browser/ui/webui/password_manager/password_manager_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/favicon_source.h"
#include "chrome/browser/ui/webui/managed_ui_handler.h"
#include "chrome/browser/ui/webui/password_manager/promo_card.h"
#include "chrome/browser/ui/webui/password_manager/promo_cards_handler.h"
#include "chrome/browser/ui/webui/password_manager/sync_handler.h"
#include "chrome/browser/ui/webui/plural_string_handler.h"
#include "chrome/browser/ui/webui/sanitized_image_source.h"
Expand Down Expand Up @@ -46,6 +44,8 @@
#endif

#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
#include "chrome/browser/ui/webui/password_manager/promo_card.h"
#include "chrome/browser/ui/webui/password_manager/promo_cards_handler.h"
#include "chrome/grit/chrome_unscaled_resources.h"
#endif

Expand Down Expand Up @@ -323,10 +323,13 @@ PasswordManagerUI::PasswordManagerUI(content::WebUI* web_ui)
true);
web_ui->AddMessageHandler(
std::make_unique<password_manager::SyncHandler>(profile));
std::vector<std::unique_ptr<password_manager::PromoCardInterface>> cards;
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
web_ui->AddMessageHandler(
std::make_unique<password_manager::PromoCardsHandler>(profile,
std::move(cards)));
std::make_unique<password_manager::PromoCardsHandler>(
profile,
password_manager::PromoCardInterface::GetAllPromoCardsForProfile(
profile)));
#endif
auto* source = CreateAndAddPasswordsUIHTMLSource(profile, web_ui);
AddPluralStrings(web_ui);
ManagedUIHandler::Initialize(web_ui, source);
Expand Down
181 changes: 181 additions & 0 deletions chrome/browser/ui/webui/password_manager/promo_card.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,46 @@

#include "chrome/browser/ui/webui/password_manager/promo_card.h"

#include "base/functional/bind.h"
#include "base/json/values_util.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/web_applications/web_app_helpers.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/password_manager/core/browser/password_manager_constants.h"
#include "components/password_manager/core/browser/password_sync_util.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/sync/driver/sync_service.h"
#include "ui/base/l10n/l10n_util.h"

namespace password_manager {

namespace {

constexpr base::TimeDelta kPasswordCheckupPromoPeriod = base::Days(7);
constexpr int kPromoDisplayLimit = 3;

constexpr char kIdKey[] = "id";
constexpr char kLastTimeShownKey[] = "last_time_shown";
constexpr char kNumberOfTimesShownKey[] = "number_of_times_shown";
constexpr char kWasDismissedKey[] = "was_dismissed";

constexpr char kCheckupPromoId[] = "password_checkup_promo";
constexpr char kWebPasswordManagerPromoId[] = "passwords_on_web_promo";
constexpr char kShortcutPromoId[] = "password_shortcut_promo";
constexpr char kAccessOnAnyDevicePromoId[] = "access_on_any_device_promo";

extern const char16_t kGetStartedOnAndroid[] =
u"https://support.google.com/chrome/?p=gpm_desktop_promo_android";
extern const char16_t kGetStartedOnIOS[] =
u"https://support.google.com/chrome/?p=gpm_desktop_promo_ios";

// Creates new pref entry for the promo card with a given id.
base::Value::Dict CreatePromoCardPrefEntry(const std::string& id) {
base::Value::Dict promo_card_pref_entry;
Expand All @@ -29,6 +56,24 @@ base::Value::Dict CreatePromoCardPrefEntry(const std::string& id) {

} // namespace

// static
std::vector<std::unique_ptr<PromoCardInterface>>
PromoCardInterface::GetAllPromoCardsForProfile(Profile* profile) {
std::vector<std::unique_ptr<PromoCardInterface>> promo_cards;
promo_cards.push_back(std::make_unique<PasswordCheckupPromo>(
profile->GetPrefs(),
extensions::PasswordsPrivateDelegateFactory::GetForBrowserContext(profile,
false)
.get()));
promo_cards.push_back(std::make_unique<WebPasswordManagerPromo>(
profile->GetPrefs(), SyncServiceFactory::GetForProfile(profile)));
promo_cards.push_back(
std::make_unique<PasswordManagerShortcutPromo>(profile));
promo_cards.push_back(
std::make_unique<AccessOnAnyDevicePromo>(profile->GetPrefs()));
return promo_cards;
}

PromoCardInterface::PromoCardInterface(const std::string& id,
PrefService* prefs)
: prefs_(prefs) {
Expand Down Expand Up @@ -84,4 +129,140 @@ void PromoCardInterface::OnPromoCardShown() {
}
}

PasswordCheckupPromo::PasswordCheckupPromo(
PrefService* prefs,
extensions::PasswordsPrivateDelegate* delegate)
: PromoCardInterface(kCheckupPromoId, prefs) {
CHECK(delegate);
delegate->GetSavedPasswordsList(base::BindOnce(
&PasswordCheckupPromo::OnPasswordsReceived, weak_factory_.GetWeakPtr()));
}

PasswordCheckupPromo::~PasswordCheckupPromo() = default;

std::string PasswordCheckupPromo::GetPromoID() const {
return kCheckupPromoId;
}

bool PasswordCheckupPromo::ShouldShowPromo() const {
if (!has_saved_passwords_) {
return false;
}
// If promo card was dismissed or shown already for kPromoDisplayLimit times,
// show it in a week next time.
bool should_suppress =
was_dismissed_ || number_of_times_shown_ >= kPromoDisplayLimit;
return !should_suppress ||
base::Time().Now() - last_time_shown_ > kPasswordCheckupPromoPeriod;
}

std::u16string PasswordCheckupPromo::GetTitle() const {
return l10n_util::GetStringUTF16(
IDS_PASSWORD_MANAGER_UI_CHECKUP_PROMO_CARD_TITLE);
}

std::u16string PasswordCheckupPromo::GetDescription() const {
return l10n_util::GetStringUTF16(
IDS_PASSWORD_MANAGER_UI_CHECKUP_PROMO_CARD_DESCRIPTION);
}

std::u16string PasswordCheckupPromo::GetActionButtonText() const {
return l10n_util::GetStringUTF16(
IDS_PASSWORD_MANAGER_UI_CHECKUP_PROMO_CARD_ACTION);
}

void PasswordCheckupPromo::OnPasswordsReceived(
const std::vector<extensions::api::passwords_private::PasswordUiEntry>&
passwords) {
has_saved_passwords_ = !passwords.empty();
}

WebPasswordManagerPromo::WebPasswordManagerPromo(
PrefService* prefs,
const syncer::SyncService* sync_service)
: PromoCardInterface(kWebPasswordManagerPromoId, prefs) {
sync_enabled_ = sync_util::IsPasswordSyncActive(sync_service);
}

std::string WebPasswordManagerPromo::GetPromoID() const {
return kWebPasswordManagerPromoId;
}

bool WebPasswordManagerPromo::ShouldShowPromo() const {
if (!sync_enabled_) {
return false;
}

return !was_dismissed_ && number_of_times_shown_ < kPromoDisplayLimit;
}

std::u16string WebPasswordManagerPromo::GetTitle() const {
return l10n_util::GetStringUTF16(
IDS_PASSWORD_MANAGER_UI_WEB_PROMO_CARD_TITLE);
}

std::u16string WebPasswordManagerPromo::GetDescription() const {
return l10n_util::GetStringFUTF16(
IDS_PASSWORD_MANAGER_UI_WEB_PROMO_CARD_DESCRIPTION,
base::ASCIIToUTF16(kPasswordManagerAccountDashboardURL));
}

PasswordManagerShortcutPromo::PasswordManagerShortcutPromo(Profile* profile)
: PromoCardInterface(kShortcutPromoId, profile->GetPrefs()) {
is_shortcut_installed_ =
web_app::FindInstalledAppWithUrlInScope(
profile, GURL(chrome::kChromeUIPasswordManagerURL))
.has_value();
}

std::string PasswordManagerShortcutPromo::GetPromoID() const {
return kShortcutPromoId;
}

bool PasswordManagerShortcutPromo::ShouldShowPromo() const {
if (is_shortcut_installed_) {
return false;
}

return !was_dismissed_ && number_of_times_shown_ < kPromoDisplayLimit;
}

std::u16string PasswordManagerShortcutPromo::GetTitle() const {
return l10n_util::GetStringUTF16(
IDS_PASSWORD_MANAGER_UI_SHORTCUT_PROMO_CARD_TITLE);
}

std::u16string PasswordManagerShortcutPromo::GetDescription() const {
return l10n_util::GetStringFUTF16(
IDS_PASSWORD_MANAGER_UI_SHORTCUT_PROMO_CARD_DESCRIPTION,
l10n_util::GetStringUTF16(
IDS_PASSWORD_BUBBLES_PASSWORD_MANAGER_LINK_TEXT_SAVING_ON_DEVICE));
}

std::u16string PasswordManagerShortcutPromo::GetActionButtonText() const {
return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_UI_ADD_SHORTCUT_TITLE);
}

AccessOnAnyDevicePromo::AccessOnAnyDevicePromo(PrefService* prefs)
: PromoCardInterface(kAccessOnAnyDevicePromoId, prefs) {}

std::string AccessOnAnyDevicePromo::GetPromoID() const {
return kAccessOnAnyDevicePromoId;
}

bool AccessOnAnyDevicePromo::ShouldShowPromo() const {
return !was_dismissed_ && number_of_times_shown_ < kPromoDisplayLimit;
}

std::u16string AccessOnAnyDevicePromo::GetTitle() const {
return l10n_util::GetStringUTF16(
IDS_PASSWORD_MANAGER_UI_ANY_DEVICE_PROMO_CARD_TITLE);
}

std::u16string AccessOnAnyDevicePromo::GetDescription() const {
return l10n_util::GetStringFUTF16(
IDS_PASSWORD_MANAGER_UI_ANY_DEVICE_PROMO_CARD_DESCRIPTION,
kGetStartedOnAndroid, kGetStartedOnIOS);
}

} // namespace password_manager

0 comments on commit 1595e16

Please sign in to comment.