chromium/chrome/browser/permissions/permission_blocked_message_delegate_android_unittest.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 "chrome/browser/permissions/permission_blocked_message_delegate_android.h"

#include "base/android/jni_android.h"
#include "base/memory/raw_ptr.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/messages/android/mock_message_dispatcher_bridge.h"
#include "components/permissions/permission_prompt.h"
#include "components/permissions/permission_request_manager.h"

namespace {

using QuietUiReason = permissions::PermissionUiSelector::QuietUiReason;

}  // namespace

class MockDelegate : public PermissionBlockedMessageDelegate::Delegate {
 public:
  ~MockDelegate() override = default;
  MockDelegate(const base::WeakPtr<permissions::PermissionPromptAndroid>&
                   permission_prompt) {}

  MOCK_METHOD(void, Accept, (), (override));
  MOCK_METHOD(void, Deny, (), (override));

  MOCK_METHOD(void, Closing, (), (override));

  MOCK_METHOD(bool, ShouldUseQuietUI, (), (override));
  MOCK_METHOD(std::optional<QuietUiReason>,
              ReasonForUsingQuietUi,
              (),
              (override));
  MOCK_METHOD(ContentSettingsType, GetContentSettingsType, (), (override));
};

class PermissionBlockedMessageDelegateAndroidTest
    : public ChromeRenderViewHostTestHarness {
 public:
  PermissionBlockedMessageDelegateAndroidTest() = default;
  ~PermissionBlockedMessageDelegateAndroidTest() override = default;

  void ExpectEnqueued() {
    EXPECT_CALL(message_dispatcher_bridge_, EnqueueMessage);
  }

  void ExpectDismiss() {
    EXPECT_CALL(message_dispatcher_bridge_, DismissMessage)
        .WillOnce([](messages::MessageWrapper* message,
                     messages::DismissReason dismiss_reason) {
          message->HandleDismissCallback(base::android::AttachCurrentThread(),
                                         static_cast<int>(dismiss_reason));
        });
  }

  void ShowMessage(std::unique_ptr<MockDelegate> delegate) {
    controller_ = std::make_unique<PermissionBlockedMessageDelegate>(
        web_contents(), std::move(delegate));
  }

  void TriggerDismiss(messages::DismissReason reason) {
    EXPECT_CALL(message_dispatcher_bridge_, DismissMessage)
        .WillOnce([&reason](messages::MessageWrapper* message,
                            messages::DismissReason dismiss_reason) {
          message->HandleDismissCallback(base::android::AttachCurrentThread(),
                                         static_cast<int>(reason));
        });
    controller_->DismissInternal();
    EXPECT_EQ(nullptr, controller_->message_.get());
  }

  void TriggerPrimaryAction() {
    controller_->HandlePrimaryActionClick();
    TriggerDismiss(messages::DismissReason::PRIMARY_ACTION);
  }

  void TriggerManageClick() { controller_->HandleManageClick(); }

  void TriggerDialogOnAllowForThisSite() {
    controller_->OnAllowForThisSite();
    controller_->OnDialogDismissed();
  }

  void TriggerDialogDismiss() { controller_->OnDialogDismissed(); }

  messages::MessageWrapper* GetMessageWrapper() {
    return controller_->message_.get();
  }

  std::unique_ptr<MockDelegate> GetMockDelegate() {
    return std::move(delegate_);
  }

 protected:
  void SetUp() override;
  void TearDown() override;

 protected:
  std::unique_ptr<PermissionBlockedMessageDelegate> controller_;
  messages::MockMessageDispatcherBridge message_dispatcher_bridge_;
  std::unique_ptr<MockDelegate> delegate_;
  raw_ptr<permissions::PermissionRequestManager> manager_ = nullptr;
};

void PermissionBlockedMessageDelegateAndroidTest::SetUp() {
  content::RenderViewHostTestHarness::SetUp();
  messages::MessageDispatcherBridge::SetInstanceForTesting(
      &message_dispatcher_bridge_);
  delegate_ = std::make_unique<MockDelegate>(nullptr);
  permissions::PermissionRequestManager::CreateForWebContents(web_contents());
  manager_ =
      permissions::PermissionRequestManager::FromWebContents(web_contents());
}

void PermissionBlockedMessageDelegateAndroidTest::TearDown() {
  messages::MessageDispatcherBridge::SetInstanceForTesting(nullptr);
  ChromeRenderViewHostTestHarness::TearDown();
}

TEST_F(PermissionBlockedMessageDelegateAndroidTest, DismissByTimeout) {
  auto delegate = GetMockDelegate();

  EXPECT_CALL(*delegate, Accept).Times(0);
  EXPECT_CALL(*delegate, Deny).Times(0);
  EXPECT_CALL(*delegate, GetContentSettingsType)
      .WillRepeatedly(testing::Return(ContentSettingsType::NOTIFICATIONS));

  ExpectEnqueued();

  ShowMessage(std::move(delegate));
  TriggerDismiss(messages::DismissReason::TIMER);
  EXPECT_EQ(nullptr, GetMessageWrapper());
}

TEST_F(PermissionBlockedMessageDelegateAndroidTest, DismissByPrimaryAction) {
  auto delegate = GetMockDelegate();
  EXPECT_CALL(*delegate, ShouldUseQuietUI)
      .WillRepeatedly(testing::Return(true));

  EXPECT_CALL(*delegate, Accept).Times(0);
  EXPECT_CALL(*delegate, Deny);
  EXPECT_CALL(*delegate, GetContentSettingsType)
      .WillRepeatedly(testing::Return(ContentSettingsType::NOTIFICATIONS));

  ExpectEnqueued();

  ShowMessage(std::move(delegate));
  TriggerPrimaryAction();
  EXPECT_EQ(nullptr, GetMessageWrapper());
}

TEST_F(PermissionBlockedMessageDelegateAndroidTest, DismissByDialogDismissed) {
  auto delegate = GetMockDelegate();

  EXPECT_CALL(*delegate, ShouldUseQuietUI)
      .WillRepeatedly(testing::Return(true));
  EXPECT_CALL(*delegate, ReasonForUsingQuietUi)
      .WillRepeatedly(testing::Return(
          std::optional<QuietUiReason>(QuietUiReason::kEnabledInPrefs)));
  EXPECT_CALL(*delegate, GetContentSettingsType)
      .WillRepeatedly(testing::Return(ContentSettingsType::NOTIFICATIONS));

  ExpectEnqueued();

  EXPECT_CALL(*delegate, Accept).Times(0);
  EXPECT_CALL(*delegate, Deny).Times(0);
  EXPECT_CALL(*delegate, Closing);

  ShowMessage(std::move(delegate));

  TriggerManageClick();
  TriggerDismiss(messages::DismissReason::SECONDARY_ACTION);
  TriggerDialogDismiss();
}

TEST_F(PermissionBlockedMessageDelegateAndroidTest,
       DismissByDialogOnAllowForThisSite) {
  auto delegate = GetMockDelegate();

  EXPECT_CALL(*delegate, ShouldUseQuietUI)
      .WillRepeatedly(testing::Return(true));
  EXPECT_CALL(*delegate, ReasonForUsingQuietUi)
      .WillRepeatedly(testing::Return(
          std::optional<QuietUiReason>(QuietUiReason::kEnabledInPrefs)));
  EXPECT_CALL(*delegate, GetContentSettingsType)
      .WillRepeatedly(testing::Return(ContentSettingsType::NOTIFICATIONS));

  ExpectEnqueued();

  EXPECT_CALL(*delegate, Accept);
  EXPECT_CALL(*delegate, Deny).Times(0);

  ShowMessage(std::move(delegate));

  TriggerManageClick();
  TriggerDismiss(messages::DismissReason::SECONDARY_ACTION);
  TriggerDialogOnAllowForThisSite();
}