blob: 9e0433f91e57ae9ee8baeaf266fe722e255de64d [file] [log] [blame]
// Copyright 2018 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/notifications/persistent_notification_handler.h"
#include <memory>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "chrome/browser/notifications/metrics/mock_notification_metrics_logger.h"
#include "chrome/browser/notifications/metrics/notification_metrics_logger_factory.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/notifications/notification_permission_context.h"
#include "chrome/browser/notifications/platform_notification_service_factory.h"
#include "chrome/browser/notifications/platform_notification_service_impl.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/permission_type.h"
#include "content/public/common/persistent_notification_status.h"
#include "content/public/test/mock_permission_manager.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/notifications/notification_resources.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
using ::testing::_;
using ::testing::Return;
namespace {
const char kExampleNotificationId[] = "example_notification_id";
const char kExampleOrigin[] = "https://example.com";
class TestingProfileWithPermissionManager : public TestingProfile {
public:
TestingProfileWithPermissionManager()
: permission_manager_(
std::make_unique<
testing::NiceMock<content::MockPermissionManager>>()) {}
~TestingProfileWithPermissionManager() override = default;
// Sets the notification permission status to |permission_status|.
void SetNotificationPermissionStatus(
blink::mojom::PermissionStatus permission_status) {
ON_CALL(*permission_manager_,
GetPermissionStatus(content::PermissionType::NOTIFICATIONS, _, _))
.WillByDefault(Return(permission_status));
}
// TestingProfile overrides:
content::PermissionControllerDelegate* GetPermissionControllerDelegate()
override {
return permission_manager_.get();
}
private:
std::unique_ptr<content::MockPermissionManager> permission_manager_;
DISALLOW_COPY_AND_ASSIGN(TestingProfileWithPermissionManager);
};
} // namespace
class PersistentNotificationHandlerTest : public ::testing::Test {
public:
PersistentNotificationHandlerTest()
: display_service_tester_(&profile_), origin_(kExampleOrigin) {}
~PersistentNotificationHandlerTest() override = default;
// ::testing::Test overrides:
void SetUp() override {
mock_logger_ = static_cast<MockNotificationMetricsLogger*>(
NotificationMetricsLoggerFactory::GetInstance()
->SetTestingFactoryAndUse(
&profile_,
base::BindRepeating(
&MockNotificationMetricsLogger::FactoryForTests)));
PlatformNotificationServiceFactory::GetForProfile(&profile_)
->ClearClosedNotificationsForTesting();
}
protected:
content::TestBrowserThreadBundle thread_bundle_;
TestingProfileWithPermissionManager profile_;
NotificationDisplayServiceTester display_service_tester_;
// The origin for which these tests are being run.
GURL origin_;
// Owned by the |profile_| as a keyed service.
MockNotificationMetricsLogger* mock_logger_ = nullptr;
private:
DISALLOW_COPY_AND_ASSIGN(PersistentNotificationHandlerTest);
};
TEST_F(PersistentNotificationHandlerTest, OnClick_WithoutPermission) {
EXPECT_CALL(*mock_logger_, LogPersistentNotificationClickWithoutPermission());
profile_.SetNotificationPermissionStatus(
blink::mojom::PermissionStatus::DENIED);
std::unique_ptr<NotificationHandler> handler =
std::make_unique<PersistentNotificationHandler>();
handler->OnClick(&profile_, origin_, kExampleNotificationId,
base::nullopt /* action_index */, base::nullopt /* reply */,
base::DoNothing());
}
TEST_F(PersistentNotificationHandlerTest,
OnClick_CloseUnactionableNotifications) {
// Show a notification for a particular origin.
{
base::RunLoop run_loop;
display_service_tester_.SetNotificationAddedClosure(run_loop.QuitClosure());
EXPECT_CALL(*mock_logger_, LogPersistentNotificationShown());
PlatformNotificationServiceFactory::GetForProfile(&profile_)
->DisplayPersistentNotification(
kExampleNotificationId, origin_ /* service_worker_scope */, origin_,
blink::PlatformNotificationData(), blink::NotificationResources());
run_loop.Run();
}
ASSERT_TRUE(display_service_tester_.GetNotification(kExampleNotificationId));
// Revoke permission for any origin to display notifications.
profile_.SetNotificationPermissionStatus(
blink::mojom::PermissionStatus::DENIED);
// Now simulate a click on the notification. It should be automatically closed
// by the PersistentNotificationHandler.
{
EXPECT_CALL(*mock_logger_,
LogPersistentNotificationClickWithoutPermission());
display_service_tester_.SimulateClick(
NotificationHandler::Type::WEB_PERSISTENT, kExampleNotificationId,
base::nullopt /* action_index */, base::nullopt /* reply */);
}
EXPECT_FALSE(display_service_tester_.GetNotification(kExampleNotificationId));
}
TEST_F(PersistentNotificationHandlerTest, OnClose_ByUser) {
EXPECT_CALL(*mock_logger_, LogPersistentNotificationClosedByUser());
std::unique_ptr<NotificationHandler> handler =
std::make_unique<PersistentNotificationHandler>();
handler->OnClose(&profile_, origin_, kExampleNotificationId,
/* by_user= */ true, base::DoNothing());
}
TEST_F(PersistentNotificationHandlerTest, OnClose_Programmatically) {
EXPECT_CALL(*mock_logger_, LogPersistentNotificationClosedProgrammatically());
std::unique_ptr<NotificationHandler> handler =
std::make_unique<PersistentNotificationHandler>();
handler->OnClose(&profile_, origin_, kExampleNotificationId,
/* by_user= */ false, base::DoNothing());
}
TEST_F(PersistentNotificationHandlerTest, DisableNotifications) {
std::unique_ptr<NotificationPermissionContext> permission_context =
std::make_unique<NotificationPermissionContext>(&profile_);
ASSERT_EQ(permission_context
->GetPermissionStatus(nullptr /* render_frame_host */, origin_,
origin_)
.content_setting,
CONTENT_SETTING_ASK);
std::unique_ptr<NotificationHandler> handler =
std::make_unique<PersistentNotificationHandler>();
handler->DisableNotifications(&profile_, origin_);
ASSERT_EQ(permission_context
->GetPermissionStatus(nullptr /* render_frame_host */, origin_,
origin_)
.content_setting,
CONTENT_SETTING_BLOCK);
}