chromium/components/blocked_content/android/popup_blocked_message_delegate.cc

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/blocked_content/android/popup_blocked_message_delegate.h"

#include "components/blocked_content/android/popup_blocked_helper.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/messages/android/message_dispatcher_bridge.h"
#include "components/prefs/pref_service.h"
#include "components/resources/android/theme_resources.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"

namespace blocked_content {

bool PopupBlockedMessageDelegate::ShowMessage(
    int num_popups,
    HostContentSettingsMap* settings_map,
    base::OnceClosure on_show_popups_callback) {
  if (message_ != nullptr) {  // update title only
    message_->SetTitle(l10n_util::GetPluralStringFUTF16(
        IDS_POPUPS_BLOCKED_INFOBAR_TEXT, num_popups));
    return false;
  }

  on_show_popups_callback_ = std::move(on_show_popups_callback);
  url_ = GetWebContents().GetLastCommittedURL();
  // Unretained is safe because |this| will always outlive |message_| which owns
  // the callback.
  auto message = std::make_unique<messages::MessageWrapper>(
      messages::MessageIdentifier::POPUP_BLOCKED,
      base::BindOnce(&PopupBlockedMessageDelegate::HandleClick,
                     base::Unretained(this)),
      base::BindOnce(&PopupBlockedMessageDelegate::HandleDismissCallback,
                     base::Unretained(this)));

  message->SetTitle(l10n_util::GetPluralStringFUTF16(
      IDS_POPUPS_BLOCKED_INFOBAR_TEXT, num_popups));

  map_ = settings_map;
  allow_settings_changes_ = !PopupSettingManagedByPolicy(map_, url_);

  // Don't allow the user to configure the setting in the UI if the setting
  // is managed by policy.
  int button_text_id =
      allow_settings_changes_ ? IDS_POPUPS_BLOCKED_INFOBAR_BUTTON_SHOW : IDS_OK;
  message->SetPrimaryButtonText(l10n_util::GetStringUTF16(button_text_id));
  messages::MessageDispatcherBridge* message_dispatcher_bridge =
      messages::MessageDispatcherBridge::Get();
  DCHECK(message_dispatcher_bridge->IsMessagesEnabledForEmbedder());
  message->SetIconResourceId(message_dispatcher_bridge->MapToJavaDrawableId(
      IDR_ANDROID_INFOBAR_BLOCKED_POPUPS));

  // On rare occasions, such as the moment when activity is being recreated
  // or destroyed, popup blocked message will not be displayed and the
  // method will return false.
  if (!message_dispatcher_bridge->EnqueueMessage(
          message.get(), &GetWebContents(),
          messages::MessageScopeType::NAVIGATION,
          messages::MessagePriority::kNormal)) {
    return false;
  }

  message_ = std::move(message);
  return true;
}

PopupBlockedMessageDelegate::~PopupBlockedMessageDelegate() {
  if (message_ != nullptr) {
    messages::MessageDispatcherBridge::Get()->DismissMessage(
        message_.get(), messages::DismissReason::UNKNOWN);
  }
}

PopupBlockedMessageDelegate::PopupBlockedMessageDelegate(
    content::WebContents* web_contents)
    : content::WebContentsUserData<PopupBlockedMessageDelegate>(*web_contents) {
}

void PopupBlockedMessageDelegate::HandleDismissCallback(
    messages::DismissReason dismiss_reason) {
  message_.reset();
  map_ = nullptr;
}

void PopupBlockedMessageDelegate::HandleClick() {
  if (!allow_settings_changes_) {
    return;
  }

  // Create exceptions.
  map_->SetNarrowestContentSetting(url_, url_, ContentSettingsType::POPUPS,
                                   CONTENT_SETTING_ALLOW);

  // Launch popups.
  ShowBlockedPopups(&GetWebContents());

  if (on_show_popups_callback_)
    std::move(on_show_popups_callback_).Run();
}

WEB_CONTENTS_USER_DATA_KEY_IMPL(PopupBlockedMessageDelegate);

}  // namespace blocked_content