// 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();
}