| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/commerce/discounts_page_action_controller.h" |
| |
| #include "components/commerce/core/commerce_feature_list.h" |
| #include "components/commerce/core/feature_utils.h" |
| #include "components/commerce/core/shopping_service.h" |
| #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| |
| namespace commerce { |
| DiscountsPageActionController::DiscountsShownData::DiscountsShownData() = |
| default; |
| DiscountsPageActionController::DiscountsShownData::~DiscountsShownData() = |
| default; |
| |
| DiscountsPageActionController::DiscountsPageActionController( |
| base::RepeatingCallback<void()> notify_callback, |
| ShoppingService* shopping_service) |
| : CommercePageActionController(std::move(notify_callback)), |
| shopping_service_(shopping_service) {} |
| |
| DiscountsPageActionController::~DiscountsPageActionController() = default; |
| |
| // static |
| DiscountsPageActionController::DiscountsShownData* |
| DiscountsPageActionController::GetOrCreate(ShoppingService* shopping_service) { |
| DiscountsShownData* data = |
| static_cast<DiscountsShownData*>(shopping_service->GetUserData( |
| DiscountsPageActionController::kDiscountsShownDataKey)); |
| if (!data) { |
| auto discounts_shown_data = std::make_unique<DiscountsShownData>(); |
| data = discounts_shown_data.get(); |
| shopping_service->SetUserData( |
| DiscountsPageActionController::kDiscountsShownDataKey, |
| std::move(discounts_shown_data)); |
| } |
| |
| return data; |
| } |
| |
| std::optional<bool> DiscountsPageActionController::ShouldShowForNavigation() { |
| if (!shopping_service_ || !IsDiscountEligibleToShowOnNavigation( |
| shopping_service_->GetAccountChecker())) { |
| return false; |
| } |
| |
| if (!got_discounts_response_for_page_) { |
| return std::nullopt; |
| } |
| |
| return !discounts_.empty(); |
| } |
| |
| bool DiscountsPageActionController::WantsExpandedUi() { |
| if (!got_discounts_response_for_page_ || discounts_.empty()) { |
| return false; |
| } |
| |
| if (!commerce::kDiscountOnShoppyPage.Get()) { |
| return true; |
| } |
| |
| std::string domain = net::registry_controlled_domains::GetDomainAndRegistry( |
| last_committed_url_, |
| net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); |
| |
| DiscountsShownData* shown_data = |
| DiscountsPageActionController::GetOrCreate(shopping_service_); |
| |
| bool has_been_shown_on_domain = |
| shown_data->discount_shown_on_domains.contains(domain); |
| |
| if (!has_been_shown_on_domain) { |
| shown_data->discount_shown_on_domains.insert(domain); |
| return true; |
| } |
| |
| for (const auto& discount_info : discounts_) { |
| if (ShouldAutoShowBubble(discount_info.id, |
| discount_info.is_merchant_wide)) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| void DiscountsPageActionController::ResetForNewNavigation(const GURL& url) { |
| if (!shopping_service_ || !IsDiscountEligibleToShowOnNavigation( |
| shopping_service_->GetAccountChecker())) { |
| return; |
| } |
| |
| // Cancel any pending callbacks. |
| weak_ptr_factory_.InvalidateWeakPtrs(); |
| |
| discounts_ = {}; |
| got_discounts_response_for_page_ = false; |
| last_committed_url_ = url; |
| NotifyHost(); |
| |
| shopping_service_->GetDiscountInfoForUrl( |
| url, |
| base::BindOnce(&DiscountsPageActionController::HandleDiscountInfoResponse, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void DiscountsPageActionController::HandleDiscountInfoResponse( |
| const GURL& url, |
| const std::vector<DiscountInfo> discounts) { |
| if (url != last_committed_url_ || discounts.empty()) { |
| got_discounts_response_for_page_ = true; |
| NotifyHost(); |
| return; |
| } |
| |
| discounts_ = std::move(discounts); |
| got_discounts_response_for_page_ = true; |
| NotifyHost(); |
| } |
| |
| const std::vector<DiscountInfo>& DiscountsPageActionController::GetDiscounts() { |
| return discounts_; |
| } |
| |
| void DiscountsPageActionController::CouponCodeCopied() { |
| coupon_code_copied_ = true; |
| } |
| |
| bool DiscountsPageActionController::IsCouponCodeCopied() { |
| bool coupon_code_copied = coupon_code_copied_; |
| coupon_code_copied_ = false; |
| return coupon_code_copied; |
| } |
| |
| bool DiscountsPageActionController::ShouldAutoShowBubble( |
| uint64_t discount_id, |
| bool is_merchant_wide) { |
| if (!shopping_service_ || !IsDiscountEligibleToShowOnNavigation( |
| shopping_service_->GetAccountChecker())) { |
| return false; |
| } |
| auto behavior = is_merchant_wide |
| ? static_cast<commerce::DiscountDialogAutoPopupBehavior>( |
| commerce::kMerchantWideBehavior.Get()) |
| : static_cast<commerce::DiscountDialogAutoPopupBehavior>( |
| commerce::kNonMerchantWideBehavior.Get()); |
| |
| switch (behavior) { |
| case commerce::DiscountDialogAutoPopupBehavior::kAutoPopupOnce: { |
| DiscountsShownData* shown_data = |
| DiscountsPageActionController::GetOrCreate(shopping_service_); |
| if (shown_data->shown_discount_ids.contains(discount_id)) { |
| return false; |
| } |
| return true; |
| } |
| case commerce::DiscountDialogAutoPopupBehavior::kAlwaysAutoPopup: |
| return true; |
| case commerce::DiscountDialogAutoPopupBehavior::kNoAutoPopup: |
| return false; |
| } |
| } |
| |
| void DiscountsPageActionController::DiscountsBubbleShown(uint64_t discount_id) { |
| DiscountsShownData* shown_data = |
| DiscountsPageActionController::GetOrCreate(shopping_service_); |
| shown_data->shown_discount_ids.insert(discount_id); |
| } |
| |
| } // namespace commerce |