From bcccd565a497dd93460427de2bcfe724b646f3fe Mon Sep 17 00:00:00 2001 From: Vishwas Uppoor <vishwasuppoor@google.com> Date: Wed, 8 Jun 2022 18:43:21 +0000 Subject: [PATCH] [Offers] Migrate Offer Notification Infobar to a Message Offers linked to payment methods on merchant sites are currently shown on an infobar. This CL shows the offers on a Message. Screenshot: https://screenshot.googleplex.com/axzyJjH4NPUuhXZ Bug: 1323077 Change-Id: I8362f4d770571d2b29b25c82e63e39caf65d0675 Validate-Test-Flakiness: skip Change-Id: I8362f4d770571d2b29b25c82e63e39caf65d0675 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3655680 Reviewed-by: Siyu An <siyua@chromium.org> Reviewed-by: Evan Stade <estade@chromium.org> Commit-Queue: Vishwas Uppoor <vishwasuppoor@chromium.org> Cr-Commit-Position: refs/heads/main@{#1012077} --- chrome/browser/ui/BUILD.gn | 4 +- .../ui/autofill/chrome_autofill_client.cc | 13 +- .../offer_notification_controller_android.cc | 117 +++++++++++ .../offer_notification_controller_android.h | 57 ++++++ ...ication_controller_android_browsertest.cc} | 183 +++++++++++++----- ...er_notification_infobar_controller_impl.cc | 50 ----- ...fer_notification_infobar_controller_impl.h | 44 ----- chrome/test/BUILD.gn | 2 +- .../browser/payments/autofill_offer_manager.h | 2 +- components/autofill_payments_strings.grdp | 11 +- ...L_OFFERS_MESSAGE_DESCRIPTION_TEXT.png.sha1 | 1 + ...FFERS_MESSAGE_PRIMARY_BUTTON_TEXT.png.sha1 | 1 + ...IDS_AUTOFILL_OFFERS_MESSAGE_TITLE.png.sha1 | 1 + 13 files changed, 329 insertions(+), 157 deletions(-) create mode 100644 chrome/browser/ui/autofill/payments/offer_notification_controller_android.cc create mode 100644 chrome/browser/ui/autofill/payments/offer_notification_controller_android.h rename chrome/browser/ui/autofill/payments/{offer_notification_infobar_controller_impl_browsertest.cc => offer_notification_controller_android_browsertest.cc} (66%) delete mode 100644 chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl.cc delete mode 100644 chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl.h create mode 100644 components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_DESCRIPTION_TEXT.png.sha1 create mode 100644 components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_PRIMARY_BUTTON_TEXT.png.sha1 create mode 100644 components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_TITLE.png.sha1 diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index efc65cf08595f..14bcf1d7aebb8 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn @@ -864,8 +864,8 @@ static_library("ui") { "autofill/payments/autofill_snackbar_controller_impl.cc", "autofill/payments/autofill_snackbar_controller_impl.h", "autofill/payments/autofill_snackbar_view.h", - "autofill/payments/offer_notification_infobar_controller_impl.cc", - "autofill/payments/offer_notification_infobar_controller_impl.h", + "autofill/payments/offer_notification_controller_android.cc", + "autofill/payments/offer_notification_controller_android.h", "autofill/payments/virtual_card_enroll_bubble_controller_impl.cc", "autofill/payments/virtual_card_enroll_bubble_controller_impl.h", "browser_otr_state_android.cc", diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index 9debc89c913c7..13c9f769fe9ed 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc @@ -95,7 +95,7 @@ #include "chrome/browser/ui/android/autofill/card_name_fix_flow_view_android.h" #include "chrome/browser/ui/android/infobars/autofill_credit_card_filling_infobar.h" #include "chrome/browser/ui/android/infobars/autofill_offer_notification_infobar.h" -#include "chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl.h" +#include "chrome/browser/ui/autofill/payments/offer_notification_controller_android.h" #include "components/autofill/core/browser/payments/autofill_credit_card_filling_infobar_delegate_mobile.h" #include "components/autofill/core/browser/payments/autofill_offer_notification_infobar_delegate_mobile.h" #include "components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h" @@ -793,8 +793,9 @@ void ChromeAutofillClient::UpdateOfferNotification( // it again. return; } - std::unique_ptr<OfferNotificationInfoBarControllerImpl> controller = - std::make_unique<OfferNotificationInfoBarControllerImpl>(web_contents()); + OfferNotificationControllerAndroid::CreateForWebContents(web_contents()); + OfferNotificationControllerAndroid* controller = + OfferNotificationControllerAndroid::FromWebContents(web_contents()); controller->ShowIfNecessary(offer, card); #else OfferNotificationBubbleControllerImpl::CreateForWebContents(web_contents()); @@ -807,9 +808,9 @@ void ChromeAutofillClient::UpdateOfferNotification( void ChromeAutofillClient::DismissOfferNotification() { #if BUILDFLAG(IS_ANDROID) - std::unique_ptr<OfferNotificationInfoBarControllerImpl> controller = - std::make_unique<OfferNotificationInfoBarControllerImpl>(web_contents()); - DCHECK(controller); + OfferNotificationControllerAndroid::CreateForWebContents(web_contents()); + OfferNotificationControllerAndroid* controller = + OfferNotificationControllerAndroid::FromWebContents(web_contents()); controller->Dismiss(); #else OfferNotificationBubbleControllerImpl* controller = diff --git a/chrome/browser/ui/autofill/payments/offer_notification_controller_android.cc b/chrome/browser/ui/autofill/payments/offer_notification_controller_android.cc new file mode 100644 index 0000000000000..4af71477dd6c5 --- /dev/null +++ b/chrome/browser/ui/autofill/payments/offer_notification_controller_android.cc @@ -0,0 +1,117 @@ +// Copyright 2022 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. + +#include "chrome/browser/ui/autofill/payments/offer_notification_controller_android.h" + +#include <memory> + +#include "chrome/browser/android/resource_mapper.h" +#include "chrome/browser/ui/android/infobars/autofill_offer_notification_infobar.h" +#include "components/autofill/core/browser/data_model/autofill_offer_data.h" +#include "components/autofill/core/browser/payments/autofill_offer_notification_infobar_delegate_mobile.h" +#include "components/grit/components_scaled_resources.h" +#include "components/infobars/content/content_infobar_manager.h" +#include "components/infobars/core/infobar.h" +#include "components/messages/android/message_dispatcher_bridge.h" +#include "components/messages/android/message_enums.h" +#include "components/messages/android/messages_feature.h" +#include "components/strings/grit/components_strings.h" +#include "ui/android/window_android.h" +#include "ui/base/l10n/l10n_util.h" + +namespace autofill { + +OfferNotificationControllerAndroid::OfferNotificationControllerAndroid( + content::WebContents* web_contents) + : content::WebContentsUserData<OfferNotificationControllerAndroid>( + *web_contents) {} + +OfferNotificationControllerAndroid::~OfferNotificationControllerAndroid() { + DismissMessage(); +} + +void OfferNotificationControllerAndroid::ShowIfNecessary( + const AutofillOfferData* offer, + const CreditCard* card) { + DCHECK(offer); + if (!card) + return; + + if (messages::IsOfferNotificationMessagesUiEnabled()) { + if (message_) { + // Dismiss the currently-shown message so that the new one can be + // displayed. + DismissMessage(); + } + message_ = std::make_unique<messages::MessageWrapper>( + messages::MessageIdentifier::OFFER_NOTIFICATION, + base::BindOnce(&OfferNotificationControllerAndroid::HandleMessageAction, + base::Unretained(this), offer->GetOfferDetailsUrl()), + base::BindOnce( + &OfferNotificationControllerAndroid::HandleMessageDismiss, + base::Unretained(this))); + message_->SetTitle( + l10n_util::GetStringUTF16(IDS_AUTOFILL_OFFERS_MESSAGE_TITLE)); + message_->SetDescription(l10n_util::GetStringFUTF16( + IDS_AUTOFILL_OFFERS_MESSAGE_DESCRIPTION_TEXT, + card->CardIdentifierStringForAutofillDisplay())); + message_->SetIconResourceId( + ResourceMapper::MapToJavaDrawableId(IDR_AUTOFILL_GOOGLE_PAY)); + message_->DisableIconTint(); + message_->SetPrimaryButtonText(l10n_util::GetStringUTF16( + IDS_AUTOFILL_OFFERS_MESSAGE_PRIMARY_BUTTON_TEXT)); + messages::MessageDispatcherBridge::Get()->EnqueueMessage( + message_.get(), &GetWebContents(), + messages::MessageScopeType::WEB_CONTENTS, + messages::MessagePriority::kNormal); + } else { + infobars::ContentInfoBarManager::FromWebContents(&GetWebContents()) + ->AddInfoBar(std::make_unique<AutofillOfferNotificationInfoBar>( + std::make_unique<AutofillOfferNotificationInfoBarDelegateMobile>( + offer->GetOfferDetailsUrl(), *card))); + } +} + +void OfferNotificationControllerAndroid::Dismiss() { + if (messages::IsOfferNotificationMessagesUiEnabled()) { + DismissMessage(); + } else { + infobars::ContentInfoBarManager* content_infobar_manager = + infobars::ContentInfoBarManager::FromWebContents(&GetWebContents()); + if (!content_infobar_manager) + return; + + for (size_t i = 0; i < content_infobar_manager->infobar_count(); ++i) { + infobars::InfoBar* infobar = content_infobar_manager->infobar_at(i); + if (infobar->delegate()->GetIdentifier() == + infobars::InfoBarDelegate:: + AUTOFILL_OFFER_NOTIFICATION_INFOBAR_DELEGATE) { + content_infobar_manager->RemoveInfoBar(infobar); + return; + } + } + } +} + +void OfferNotificationControllerAndroid::DismissMessage() { + if (message_) { + messages::MessageDispatcherBridge::Get()->DismissMessage( + message_.get(), messages::DismissReason::UNKNOWN); + } +} + +void OfferNotificationControllerAndroid::HandleMessageAction(const GURL& url) { + GetWebContents().OpenURL(content::OpenURLParams( + url, content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui::PAGE_TRANSITION_LINK, false)); +} + +void OfferNotificationControllerAndroid::HandleMessageDismiss( + messages::DismissReason dismiss_reason) { + message_.reset(); +} + +WEB_CONTENTS_USER_DATA_KEY_IMPL(OfferNotificationControllerAndroid); + +} // namespace autofill diff --git a/chrome/browser/ui/autofill/payments/offer_notification_controller_android.h b/chrome/browser/ui/autofill/payments/offer_notification_controller_android.h new file mode 100644 index 0000000000000..e9df765ed4eda --- /dev/null +++ b/chrome/browser/ui/autofill/payments/offer_notification_controller_android.h @@ -0,0 +1,57 @@ +// Copyright 2022 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. + +#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_OFFER_NOTIFICATION_CONTROLLER_ANDROID_H_ +#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_OFFER_NOTIFICATION_CONTROLLER_ANDROID_H_ + +#include "base/memory/raw_ptr.h" +#include "components/autofill/core/browser/data_model/credit_card.h" +#include "components/messages/android/message_wrapper.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace autofill { + +class AutofillOfferData; + +// Per-tab controller to control the offer notification infobar / message +// displayed on mobile. +class OfferNotificationControllerAndroid + : public content::WebContentsUserData<OfferNotificationControllerAndroid> { + public: + explicit OfferNotificationControllerAndroid( + content::WebContents* web_contents); + ~OfferNotificationControllerAndroid() override; + + OfferNotificationControllerAndroid( + const OfferNotificationControllerAndroid&) = delete; + OfferNotificationControllerAndroid& operator=( + const OfferNotificationControllerAndroid&) = delete; + + // Show the infobar / message unless it was already shown in the same tab with + // the same origin. + void ShowIfNecessary(const AutofillOfferData* offer, const CreditCard* card); + + // Dismiss the infobar / message if it is visible. + void Dismiss(); + + private: + friend class content::WebContentsUserData<OfferNotificationControllerAndroid>; + + // Dismiss the message if it is visible. + void DismissMessage(); + + // Callbacks for user selection on offer notification message. + void HandleMessageAction(const GURL& url); + void HandleMessageDismiss(messages::DismissReason dismiss_reason); + + // Delegate of a toast style popup showing in the top of the screen. + std::unique_ptr<messages::MessageWrapper> message_; + + WEB_CONTENTS_USER_DATA_KEY_DECL(); +}; + +} // namespace autofill + +#endif // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_OFFER_NOTIFICATION_CONTROLLER_ANDROID_H_ diff --git a/chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl_browsertest.cc b/chrome/browser/ui/autofill/payments/offer_notification_controller_android_browsertest.cc similarity index 66% rename from chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl_browsertest.cc rename to chrome/browser/ui/autofill/payments/offer_notification_controller_android_browsertest.cc index ffd6436a13bca..35246819d8089 100644 --- a/chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl_browsertest.cc +++ b/chrome/browser/ui/autofill/payments/offer_notification_controller_android_browsertest.cc @@ -3,10 +3,11 @@ // found in the LICENSE file. #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "chrome/browser/autofill/autofill_uitest_util.h" #include "chrome/browser/autofill/personal_data_manager_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl.h" +#include "chrome/browser/ui/autofill/payments/offer_notification_controller_android.h" #include "chrome/test/base/android/android_browser_test.h" #include "chrome/test/base/chrome_test_utils.h" #include "components/autofill/content/browser/content_autofill_driver.h" @@ -19,6 +20,9 @@ #include "components/infobars/content/content_infobar_manager.h" #include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar_delegate.h" +#include "components/messages/android/message_enums.h" +#include "components/messages/android/messages_feature.h" +#include "components/messages/android/test/messages_test_helper.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -29,11 +33,11 @@ namespace autofill { const char kHostName[] = "example.com"; -class OfferNotificationInfoBarControllerImplBrowserTest +class OfferNotificationControllerAndroidBrowserTest : public AndroidBrowserTest { public: - OfferNotificationInfoBarControllerImplBrowserTest() = default; - ~OfferNotificationInfoBarControllerImplBrowserTest() override = default; + OfferNotificationControllerAndroidBrowserTest() = default; + ~OfferNotificationControllerAndroidBrowserTest() override = default; void SetUp() override { AndroidBrowserTest::SetUp(); @@ -44,30 +48,6 @@ class OfferNotificationInfoBarControllerImplBrowserTest return chrome_test_utils::GetActiveWebContents(this); } - infobars::InfoBar* GetInfoBar() { - infobars::ContentInfoBarManager* infobar_manager = - infobars::ContentInfoBarManager::FromWebContents(GetWebContents()); - for (size_t i = 0; i < infobar_manager->infobar_count(); ++i) { - infobars::InfoBar* infobar = infobar_manager->infobar_at(i); - if (infobar->delegate()->GetIdentifier() == - infobars::InfoBarDelegate:: - AUTOFILL_OFFER_NOTIFICATION_INFOBAR_DELEGATE) { - return infobar; - } - } - return nullptr; - } - - AutofillOfferNotificationInfoBarDelegateMobile* GetInfoBarDelegate( - infobars::InfoBar* infobar) { - return static_cast<AutofillOfferNotificationInfoBarDelegateMobile*>( - infobar->delegate()); - } - - void ShowOfferNotificationInfoBar(const AutofillOfferData* offer) { - offer_notification_infobar_controller_->ShowIfNecessary(offer, &card_); - } - AutofillOfferData CreateTestCardLinkedOffer( const std::vector<GURL>& merchant_origins, const std::vector<int64_t>& eligible_instrument_ids, @@ -81,19 +61,6 @@ class OfferNotificationInfoBarControllerImplBrowserTest offer_reward_amount); } - void VerifyInfoBarShownCount(int count) { - histogram_tester_.ExpectTotalCount( - "Autofill.OfferNotificationInfoBarOffer.CardLinkedOffer", count); - } - - void VerifyInfoBarResultMetric( - AutofillMetrics::OfferNotificationInfoBarResultMetric metric, - int count) { - histogram_tester_.ExpectBucketCount( - "Autofill.OfferNotificationInfoBarResult.CardLinkedOffer", metric, - count); - } - GURL GetInitialUrl() { return embedded_test_server()->GetURL(kHostName, "/empty.html"); } @@ -104,9 +71,8 @@ class OfferNotificationInfoBarControllerImplBrowserTest // Wait for Personal Data Manager to be fully loaded to prevent that // spurious notifications deceive the tests. WaitForPersonalDataManagerToBeLoaded(GetProfile()); - offer_notification_infobar_controller_ = - std::make_unique<OfferNotificationInfoBarControllerImpl>( - GetWebContents()); + offer_notification_controller_android_ = + std::make_unique<OfferNotificationControllerAndroid>(GetWebContents()); host_resolver()->AddRule("*", "127.0.0.1"); embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data"); ASSERT_TRUE(embedded_test_server()->Start()); @@ -150,17 +116,70 @@ class OfferNotificationInfoBarControllerImplBrowserTest handler->AddShownNotificationIdForTesting(id); } - private: - std::unique_ptr<OfferNotificationInfoBarControllerImpl> - offer_notification_infobar_controller_; - // CreditCard that is linked to the offer displayed in the offer notification - // infobar. + protected: + std::unique_ptr<OfferNotificationControllerAndroid> + offer_notification_controller_android_; + // CreditCard that is linked to the offer displayed in the offer notification. CreditCard card_; base::HistogramTester histogram_tester_; + base::test::ScopedFeatureList scoped_feature_list_; + + private: PersonalDataManager* personal_data_; }; -IN_PROC_BROWSER_TEST_F(OfferNotificationInfoBarControllerImplBrowserTest, +class OfferNotificationControllerAndroidBrowserTestForInfobar + : public OfferNotificationControllerAndroidBrowserTest { + public: + OfferNotificationControllerAndroidBrowserTestForInfobar() = default; + + void SetUp() override { + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{}, + /*disabled_features=*/{messages::kMessagesForAndroidInfrastructure, + messages::kMessagesForAndroidOfferNotification}); + OfferNotificationControllerAndroidBrowserTest::SetUp(); + } + + infobars::InfoBar* GetInfoBar() { + infobars::ContentInfoBarManager* infobar_manager = + infobars::ContentInfoBarManager::FromWebContents(GetWebContents()); + for (size_t i = 0; i < infobar_manager->infobar_count(); ++i) { + infobars::InfoBar* infobar = infobar_manager->infobar_at(i); + if (infobar->delegate()->GetIdentifier() == + infobars::InfoBarDelegate:: + AUTOFILL_OFFER_NOTIFICATION_INFOBAR_DELEGATE) { + return infobar; + } + } + return nullptr; + } + + AutofillOfferNotificationInfoBarDelegateMobile* GetInfoBarDelegate( + infobars::InfoBar* infobar) { + return static_cast<AutofillOfferNotificationInfoBarDelegateMobile*>( + infobar->delegate()); + } + + void ShowOfferNotificationInfoBar(const AutofillOfferData* offer) { + offer_notification_controller_android_->ShowIfNecessary(offer, &card_); + } + + void VerifyInfoBarShownCount(int count) { + histogram_tester_.ExpectTotalCount( + "Autofill.OfferNotificationInfoBarOffer.CardLinkedOffer", count); + } + + void VerifyInfoBarResultMetric( + AutofillMetrics::OfferNotificationInfoBarResultMetric metric, + int count) { + histogram_tester_.ExpectBucketCount( + "Autofill.OfferNotificationInfoBarResult.CardLinkedOffer", metric, + count); + } +}; + +IN_PROC_BROWSER_TEST_F(OfferNotificationControllerAndroidBrowserTestForInfobar, ShowInfobarAndAccept) { GURL offer_url = GetInitialUrl().DeprecatedGetOriginAsURL(); SetUpOfferDataWithDomains(offer_url); @@ -181,7 +200,7 @@ IN_PROC_BROWSER_TEST_F(OfferNotificationInfoBarControllerImplBrowserTest, 1); } -IN_PROC_BROWSER_TEST_F(OfferNotificationInfoBarControllerImplBrowserTest, +IN_PROC_BROWSER_TEST_F(OfferNotificationControllerAndroidBrowserTestForInfobar, ShowInfobarAndClose) { GURL offer_url = GetInitialUrl().DeprecatedGetOriginAsURL(); SetUpOfferDataWithDomains(offer_url); @@ -202,7 +221,7 @@ IN_PROC_BROWSER_TEST_F(OfferNotificationInfoBarControllerImplBrowserTest, 1); } -IN_PROC_BROWSER_TEST_F(OfferNotificationInfoBarControllerImplBrowserTest, +IN_PROC_BROWSER_TEST_F(OfferNotificationControllerAndroidBrowserTestForInfobar, CrossTabStatusTracking) { GURL offer_url = GetInitialUrl().DeprecatedGetOriginAsURL(); int64_t id = SetUpOfferDataWithDomains(offer_url)->GetOfferId(); @@ -219,4 +238,64 @@ IN_PROC_BROWSER_TEST_F(OfferNotificationInfoBarControllerImplBrowserTest, VerifyInfoBarShownCount(0); } +class OfferNotificationControllerAndroidBrowserTestForMessagesUi + : public OfferNotificationControllerAndroidBrowserTest { + public: + OfferNotificationControllerAndroidBrowserTestForMessagesUi() = default; + + void SetUp() override { + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{messages::kMessagesForAndroidInfrastructure, + messages::kMessagesForAndroidOfferNotification}, + /*disabled_features=*/{}); + OfferNotificationControllerAndroidBrowserTest::SetUp(); + } + + void VerifyMessageShownCountMetric(int count) { + histogram_tester_.ExpectBucketCount( + "Android.Messages.Enqueued.Visible", + static_cast<int>(messages::MessageIdentifier::OFFER_NOTIFICATION), + count); + } + + messages::MessagesTestHelper messages_test_helper_; +}; + +IN_PROC_BROWSER_TEST_F( + OfferNotificationControllerAndroidBrowserTestForMessagesUi, + MessageShown) { + GURL offer_url = GetInitialUrl().DeprecatedGetOriginAsURL(); + SetUpOfferDataWithDomains(offer_url); + ASSERT_TRUE(content::NavigateToURL(GetWebContents(), GetInitialUrl())); + // Verify that the message was shown and logged. + EXPECT_EQ(messages_test_helper_.GetMessageCount( + GetWebContents()->GetTopLevelNativeWindow()), + 1); + EXPECT_EQ( + messages_test_helper_.GetMessageIdentifier( + GetWebContents()->GetTopLevelNativeWindow(), /* enqueue index */ 0), + static_cast<int>(messages::MessageIdentifier::OFFER_NOTIFICATION)); + VerifyMessageShownCountMetric(1); +} + +IN_PROC_BROWSER_TEST_F( + OfferNotificationControllerAndroidBrowserTestForMessagesUi, + CrossTabStatusTracking) { + GURL offer_url = GetInitialUrl().DeprecatedGetOriginAsURL(); + int64_t id = SetUpOfferDataWithDomains(offer_url)->GetOfferId(); + + SetShownOffer(id); + // Navigate to a different URL within the same domain and try to show the + // message. + offer_url = embedded_test_server()->GetURL(kHostName, "/simple_page.html"); + ASSERT_TRUE(content::NavigateToURL(GetWebContents(), offer_url)); + + // Verify that the message was not shown again because it has already been + // marked as shown for this domain. + EXPECT_EQ(messages_test_helper_.GetMessageCount( + GetWebContents()->GetTopLevelNativeWindow()), + 0); + VerifyMessageShownCountMetric(0); +} + } // namespace autofill diff --git a/chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl.cc b/chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl.cc deleted file mode 100644 index 8b5e15531bd25..0000000000000 --- a/chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl.cc +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2021 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. - -#include "chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl.h" - -#include "chrome/browser/ui/android/infobars/autofill_offer_notification_infobar.h" -#include "components/autofill/core/browser/data_model/autofill_offer_data.h" -#include "components/autofill/core/browser/payments/autofill_offer_notification_infobar_delegate_mobile.h" -#include "components/infobars/content/content_infobar_manager.h" -#include "components/infobars/core/infobar.h" -#include "ui/android/window_android.h" - -namespace autofill { - -OfferNotificationInfoBarControllerImpl::OfferNotificationInfoBarControllerImpl( - content::WebContents* contents) - : web_contents_(contents) {} - -void OfferNotificationInfoBarControllerImpl::ShowIfNecessary( - const AutofillOfferData* offer, - const CreditCard* card) { - DCHECK(offer); - if (!card) - return; - - infobars::ContentInfoBarManager::FromWebContents(web_contents_) - ->AddInfoBar(std::make_unique<AutofillOfferNotificationInfoBar>( - std::make_unique<AutofillOfferNotificationInfoBarDelegateMobile>( - offer->GetOfferDetailsUrl(), *card))); -} - -void OfferNotificationInfoBarControllerImpl::Dismiss() { - infobars::ContentInfoBarManager* content_infobar_manager = - infobars::ContentInfoBarManager::FromWebContents(web_contents_); - if (!content_infobar_manager) - return; - - for (size_t i = 0; i < content_infobar_manager->infobar_count(); ++i) { - infobars::InfoBar* infobar = content_infobar_manager->infobar_at(i); - if (infobar->delegate()->GetIdentifier() == - infobars::InfoBarDelegate:: - AUTOFILL_OFFER_NOTIFICATION_INFOBAR_DELEGATE) { - content_infobar_manager->RemoveInfoBar(infobar); - return; - } - } -} - -} // namespace autofill diff --git a/chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl.h b/chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl.h deleted file mode 100644 index 7b45961b831b5..0000000000000 --- a/chrome/browser/ui/autofill/payments/offer_notification_infobar_controller_impl.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2021 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. - -#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_OFFER_NOTIFICATION_INFOBAR_CONTROLLER_IMPL_H_ -#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_OFFER_NOTIFICATION_INFOBAR_CONTROLLER_IMPL_H_ - -#include "base/memory/raw_ptr.h" -#include "components/autofill/core/browser/data_model/credit_card.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" - -namespace autofill { - -class AutofillOfferData; - -// Per-tab controller to control the offer notification infobar displayed on -// mobile. -class OfferNotificationInfoBarControllerImpl { - public: - explicit OfferNotificationInfoBarControllerImpl( - content::WebContents* contents); - ~OfferNotificationInfoBarControllerImpl() = default; - - OfferNotificationInfoBarControllerImpl( - const OfferNotificationInfoBarControllerImpl&) = delete; - OfferNotificationInfoBarControllerImpl& operator=( - const OfferNotificationInfoBarControllerImpl&) = delete; - - // Show the infobar unless it was already shown in the same tab with the same - // origin. - void ShowIfNecessary(const AutofillOfferData* offer, const CreditCard* card); - - // Dismiss the infobar if it is visible. - void Dismiss(); - - private: - raw_ptr<content::WebContents> web_contents_; -}; - -} // namespace autofill - -#endif // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_OFFER_NOTIFICATION_INFOBAR_CONTROLLER_IMPL_H_ diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index f8455544b6ca7..bc88312a4b42d 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn @@ -853,7 +853,7 @@ if (is_android) { "../browser/ssl/crlset_browsertest.cc", "../browser/subresource_filter/subresource_filter_browser_test_harness.cc", "../browser/subresource_filter/subresource_filter_browser_test_harness.h", - "../browser/ui/autofill/payments/offer_notification_infobar_controller_impl_browsertest.cc", + "../browser/ui/autofill/payments/offer_notification_controller_android_browsertest.cc", "../browser/ui/webui/policy/policy_ui_browsertest.cc", "../renderer/autofill/fake_mojo_password_manager_driver.cc", "../renderer/autofill/fake_mojo_password_manager_driver.h", diff --git a/components/autofill/core/browser/payments/autofill_offer_manager.h b/components/autofill/core/browser/payments/autofill_offer_manager.h index 1a49cc4e21f64..a444c6ec6a876 100644 --- a/components/autofill/core/browser/payments/autofill_offer_manager.h +++ b/components/autofill/core/browser/payments/autofill_offer_manager.h @@ -78,7 +78,7 @@ class AutofillOfferManager : public KeyedService, CreateCardLinkedOffersMap_ReturnsOnlyCardLinkedOffers); FRIEND_TEST_ALL_PREFIXES(AutofillOfferManagerTest, IsUrlEligible); friend class OfferNotificationBubbleViewsInteractiveUiTest; - friend class OfferNotificationInfoBarControllerImplBrowserTest; + friend class OfferNotificationControllerAndroidBrowserTest; // Queries |personal_data_| to reset the elements of // |eligible_merchant_domains_| diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp index c14e8b157f589..b0d811e81d6ab 100644 --- a/components/autofill_payments_strings.grdp +++ b/components/autofill_payments_strings.grdp @@ -671,12 +671,21 @@ </message> </if> <if expr="is_android"> - <message name="IDS_AUTOFILL_OFFERS_REMINDER_DESCRIPTION_TEXT" desc="Secondary explanatory text for the Clank infobar shown on the merchant website when an offer is available to use." formatter_data="android_java"> + <message name="IDS_AUTOFILL_OFFERS_REMINDER_DESCRIPTION_TEXT" desc="Secondary explanatory text for the infobar shown on the merchant website when an offer is available to use." formatter_data="android_java"> Pay with <ph name="CARD_DETAIL">%1$s<ex>Visa - 1234</ex></ph> at checkout. </message> <message name="IDS_AUTOFILL_OFFERS_REMINDER_DEEP_LINK_TEXT" desc="Text to be linked to take the user to the offer in the Google Pay app." formatter_data="android_java"> See details </message> + <message name="IDS_AUTOFILL_OFFERS_MESSAGE_TITLE" desc="Title of the message shown on the merchant website when a GPay-activated card linked offer is available to use."> + Google Pay offer available + </message> + <message name="IDS_AUTOFILL_OFFERS_MESSAGE_DESCRIPTION_TEXT" desc="Secondary explanatory text for the message shown on the merchant website when an offer is available to use."> + Check out with <ph name="CARD_DETAIL">$1<ex>Visa - 1234</ex></ph> to use offer + </message> + <message name="IDS_AUTOFILL_OFFERS_MESSAGE_PRIMARY_BUTTON_TEXT" desc="Text for the primary button of the message shown on the merchant website when a GPay-activated card linked offer is available to use."> + Details + </message> </if> <if expr="toolkit_views"> <message name="IDS_AUTOFILL_PROMO_CODE_OFFERS_REMINDER_TITLE" desc="Title of the bubble shown on the merchant website when a merchant promo code offer is available to use."> diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_DESCRIPTION_TEXT.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_DESCRIPTION_TEXT.png.sha1 new file mode 100644 index 0000000000000..bbbd9c4502a3f --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_DESCRIPTION_TEXT.png.sha1 @@ -0,0 +1 @@ +587b54e3577dbb3f64e126b4d7c01c4480bac10e \ No newline at end of file diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_PRIMARY_BUTTON_TEXT.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_PRIMARY_BUTTON_TEXT.png.sha1 new file mode 100644 index 0000000000000..3072d2f3e4ea4 --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_PRIMARY_BUTTON_TEXT.png.sha1 @@ -0,0 +1 @@ +33628376178104d1b7a0adddac1e4bd96995e208 \ No newline at end of file diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_TITLE.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_TITLE.png.sha1 new file mode 100644 index 0000000000000..4a9273aae5935 --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_OFFERS_MESSAGE_TITLE.png.sha1 @@ -0,0 +1 @@ +1f41b89f1889a8e89497daf7d63ac16bf0113bd2 \ No newline at end of file