blob: 11c6f3737039a32a67156a069927edcf319c9768 [file] [log] [blame]
// Copyright 2015 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/push_messaging/push_messaging_notification_manager.h"
#include "base/functional/bind.h"
#include "base/strings/stringprintf.h"
#include "build/chromeos_buildflags.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_renderer_host.h"
#include "extensions/buildflags/buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/browser/extensions/chrome_test_extension_loader.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_service_test_with_install.h"
#include "extensions/common/extension.h"
#include "extensions/test/test_extension_dir.h"
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
class PushMessagingNotificationManagerTest
: public ChromeRenderViewHostTestHarness {};
TEST_F(PushMessagingNotificationManagerTest, IsTabVisible) {
PushMessagingNotificationManager manager(profile());
GURL origin("https://google.com/");
GURL origin_with_path = origin.Resolve("/path/");
NavigateAndCommit(origin_with_path);
EXPECT_FALSE(manager.IsTabVisible(profile(), nullptr, origin));
EXPECT_FALSE(manager.IsTabVisible(profile(), web_contents(),
GURL("https://chrome.com/")));
EXPECT_TRUE(manager.IsTabVisible(profile(), web_contents(), origin));
content::RenderViewHostTester::For(rvh())->SimulateWasHidden();
EXPECT_FALSE(manager.IsTabVisible(profile(), web_contents(), origin));
content::RenderViewHostTester::For(rvh())->SimulateWasShown();
EXPECT_TRUE(manager.IsTabVisible(profile(), web_contents(), origin));
}
TEST_F(PushMessagingNotificationManagerTest, IsTabVisibleViewSource) {
PushMessagingNotificationManager manager(profile());
GURL origin("https://google.com/");
GURL view_source_page("view-source:https://google.com/path/");
NavigateAndCommit(view_source_page);
ASSERT_EQ(view_source_page, web_contents()->GetVisibleURL());
EXPECT_TRUE(manager.IsTabVisible(profile(), web_contents(), origin));
content::RenderViewHostTester::For(rvh())->SimulateWasHidden();
EXPECT_FALSE(manager.IsTabVisible(profile(), web_contents(), origin));
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
namespace extensions {
using ContextType = extensions::browser_test_util::ContextType;
class ExtensionsPushMessagingNotificationManagerTest
: public ExtensionServiceTestWithInstall,
public testing::WithParamInterface<ContextType> {
public:
ExtensionsPushMessagingNotificationManagerTest() = default;
ExtensionsPushMessagingNotificationManagerTest(
const ExtensionsPushMessagingNotificationManagerTest&) = delete;
ExtensionsPushMessagingNotificationManagerTest& operator=(
const ExtensionsPushMessagingNotificationManagerTest&) = delete;
void SetUp() override {
ExtensionServiceTestWithInstall::SetUp();
InitializeExtensionService(ExtensionServiceInitParams());
}
};
// Tests that when receiving a push message only service worker-based extensions
// are allowed to bypass/skip the user visible notification requirement only if
// they set userVisible == false when they subscribed to the push server.
TEST_P(ExtensionsPushMessagingNotificationManagerTest,
SkipEnforceUserVisibleOnlyRequirements_ForExtensions) {
static constexpr char kManifestPersistentBackgroundScript[] =
R"({"scripts": ["background.js"], "persistent": true})";
static constexpr char kManifestEventPageBackgroundScript[] =
R"({"persistent": false,
"scripts": ["background.js"]
}
)";
static constexpr char kManifestServiceWorkerBackgroundScript[] =
R"({"service_worker": "background.js"})";
// Load an extension of ContextType.
TestExtensionDir test_dir;
constexpr char kManifest[] =
R"({
"name": "Test Extension",
"manifest_version": %s,
"version": "0.1",
"background": %s,
"permissions": ["notifications"]
})";
ContextType extension_context_type = GetParam();
bool worker_extension = extension_context_type == ContextType::kServiceWorker;
const char* background_script;
if (worker_extension) {
background_script = kManifestServiceWorkerBackgroundScript;
} else if (extension_context_type == ContextType::kEventPage) {
background_script = kManifestEventPageBackgroundScript;
} else {
background_script = kManifestPersistentBackgroundScript;
}
const char* manifest_version = worker_extension ? "3" : "2";
std::string manifest =
base::StringPrintf(kManifest, manifest_version, background_script);
test_dir.WriteManifest(manifest);
test_dir.WriteFile(FILE_PATH_LITERAL("background.js"), "");
ChromeTestExtensionLoader loader(profile());
scoped_refptr<const Extension> extension =
loader.LoadExtension(test_dir.UnpackedPath());
ASSERT_TRUE(extension);
// Attempt to skip while userVisible == false.
bool skip_allowed = false;
PushMessagingNotificationManager manager(profile());
manager.EnforceUserVisibleOnlyRequirements(
Extension::GetBaseURLFromExtensionId(extension->id()), 0l,
// Callback that is called when user visible requirements are skipped.
base::BindOnce(
[](bool* skip_allowed, bool did_show_generic_notification) {
*skip_allowed = true;
// Generic notifications are shown if the push subscriber didn't
// show a user visible notification when receiving a push
// notification.
EXPECT_FALSE(did_show_generic_notification);
},
&skip_allowed),
/*requested_user_visible_only=*/true); // userVisible == false
// Only workers are allowed to skip the userVisible notification.
if (worker_extension) {
EXPECT_TRUE(skip_allowed);
} else {
EXPECT_FALSE(skip_allowed);
}
// Attempt to skip while userVisible == true.
skip_allowed = false;
manager.EnforceUserVisibleOnlyRequirements(
Extension::GetBaseURLFromExtensionId(extension->id()), 0l,
// Callback that is called when user visible requirements are skipped.
base::BindOnce(
[](bool* skip_allowed, bool did_show_generic_notification) {
*skip_allowed = true;
// Generic notifications are shown if the push subscriber didn't
// show a user visible notification when receiving a push
// notification.
EXPECT_FALSE(did_show_generic_notification);
},
&skip_allowed),
/*requested_user_visible_only=*/false); // userVisible == true
// If userVisible == true then no matter the extension context type we should
// not skip.
EXPECT_FALSE(skip_allowed);
}
INSTANTIATE_TEST_SUITE_P(
NonWorkerExtension,
ExtensionsPushMessagingNotificationManagerTest,
::testing::ValuesIn({ContextType::kEventPage,
ContextType::kPersistentBackground}));
INSTANTIATE_TEST_SUITE_P(WorkerBasedExtension,
ExtensionsPushMessagingNotificationManagerTest,
::testing::Values(ContextType::kServiceWorker));
} // namespace extensions
#endif // BUILDFLAG(ENABLE_EXTENSIONS)