blob: 770822f02475b86bb4d2788d725dd7985edaa9b8 [file] [log] [blame]
// Copyright 2015 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 "base/strings/string_number_conversions.h"
#include "content/browser/notifications/notification_id_generator.h"
#include "content/public/test/test_browser_context.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content {
namespace {
const int kRenderProcessId = 42;
const int64_t kPersistentNotificationId = 430;
const int kNonPersistentNotificationId = 5400;
const char kExampleTag[] = "example";
class TestBrowserContextConfigurableIncognito : public TestBrowserContext {
public:
TestBrowserContextConfigurableIncognito() {}
~TestBrowserContextConfigurableIncognito() override {}
void set_incognito(bool incognito) { incognito_ = incognito; }
// TestBrowserContext implementation.
bool IsOffTheRecord() const override { return incognito_; }
private:
bool incognito_ = false;
DISALLOW_COPY_AND_ASSIGN(TestBrowserContextConfigurableIncognito);
};
class NotificationIdGeneratorTest : public ::testing::Test {
public:
NotificationIdGeneratorTest()
: generator_(&browser_context_, kRenderProcessId) {}
void SetUp() override {
}
protected:
GURL origin() const { return GURL("https://example.com"); }
TestBrowserContextConfigurableIncognito* browser_context() {
return &browser_context_;
}
NotificationIdGenerator* generator() { return &generator_; }
private:
TestBrowserContextConfigurableIncognito browser_context_;
NotificationIdGenerator generator_;
};
// -----------------------------------------------------------------------------
// Persistent and non-persistent notifications
//
// Tests that cover logic common to both persistent and non-persistent
// notifications: different browser contexts, Incognito mode or not,
// Two calls to the generator with exactly the same information should result
// in exactly the same notification ids being generated.
TEST_F(NotificationIdGeneratorTest, DeterministicGeneration) {
// Persistent notifications.
EXPECT_EQ(
generator()->GenerateForPersistentNotification(
origin(), kExampleTag, kPersistentNotificationId),
generator()->GenerateForPersistentNotification(
origin(), kExampleTag, kPersistentNotificationId));
EXPECT_EQ(
generator()->GenerateForPersistentNotification(
origin(), "" /* tag */, kPersistentNotificationId),
generator()->GenerateForPersistentNotification(
origin(), "" /* tag */, kPersistentNotificationId));
// Non-persistent notifications.
EXPECT_EQ(
generator()->GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId),
generator()->GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId));
EXPECT_EQ(
generator()->GenerateForNonPersistentNotification(
origin(), "" /* tag */, kNonPersistentNotificationId),
generator()->GenerateForNonPersistentNotification(
origin(), "" /* tag */, kNonPersistentNotificationId));
}
// Uniqueness of notification ids will be impacted by the browser context.
TEST_F(NotificationIdGeneratorTest, DifferentBrowserContexts) {
TestBrowserContextConfigurableIncognito second_browser_context;
NotificationIdGenerator second_generator(&second_browser_context,
kRenderProcessId);
// Persistent notifications.
EXPECT_NE(
generator()->GenerateForPersistentNotification(
origin(), kExampleTag, kPersistentNotificationId),
second_generator.GenerateForPersistentNotification(
origin(), kExampleTag, kPersistentNotificationId));
EXPECT_NE(
generator()->GenerateForPersistentNotification(
origin(), "" /* tag */, kPersistentNotificationId),
second_generator.GenerateForPersistentNotification(
origin(), "" /* tag */, kPersistentNotificationId));
// Non-persistent notifications.
EXPECT_NE(
generator()->GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId),
second_generator.GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId));
EXPECT_NE(
generator()->GenerateForNonPersistentNotification(
origin(), "" /* tag */, kNonPersistentNotificationId),
second_generator.GenerateForNonPersistentNotification(
origin(), "" /* tag */, kNonPersistentNotificationId));
}
// Uniqueness of notification ids will be impacted by the fact whether the
// browser context is in Incognito mode.
TEST_F(NotificationIdGeneratorTest, DifferentIncognitoStates) {
ASSERT_FALSE(browser_context()->IsOffTheRecord());
// Persistent notifications.
std::string normal_persistent_notification_id =
generator()->GenerateForPersistentNotification(
origin(), kExampleTag, kPersistentNotificationId);
browser_context()->set_incognito(true);
ASSERT_TRUE(browser_context()->IsOffTheRecord());
std::string incognito_persistent_notification_id =
generator()->GenerateForPersistentNotification(
origin(), kExampleTag, kPersistentNotificationId);
EXPECT_NE(normal_persistent_notification_id,
incognito_persistent_notification_id);
browser_context()->set_incognito(false);
// Non-persistent notifications.
ASSERT_FALSE(browser_context()->IsOffTheRecord());
std::string normal_non_persistent_notification_id =
generator()->GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId);
browser_context()->set_incognito(true);
ASSERT_TRUE(browser_context()->IsOffTheRecord());
std::string incognito_non_persistent_notification_id =
generator()->GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId);
EXPECT_NE(normal_non_persistent_notification_id,
incognito_non_persistent_notification_id);
}
// The origin of the notification will impact the generated notification id.
TEST_F(NotificationIdGeneratorTest, DifferentOrigins) {
GURL different_origin("https://example2.com");
// Persistent notifications.
EXPECT_NE(
generator()->GenerateForPersistentNotification(
origin(), kExampleTag, kPersistentNotificationId),
generator()->GenerateForPersistentNotification(
different_origin, kExampleTag, kPersistentNotificationId));
// Non-persistent notifications.
EXPECT_NE(
generator()->GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId),
generator()->GenerateForNonPersistentNotification(
different_origin, kExampleTag, kNonPersistentNotificationId));
}
// The tag, when non-empty, will impact the generated notification id.
TEST_F(NotificationIdGeneratorTest, DifferentTags) {
const std::string& different_tag = std::string(kExampleTag) + "2";
// Persistent notifications.
EXPECT_NE(
generator()->GenerateForPersistentNotification(
origin(), kExampleTag, kPersistentNotificationId),
generator()->GenerateForPersistentNotification(
origin(), different_tag, kPersistentNotificationId));
// Non-persistent notifications.
EXPECT_NE(
generator()->GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId),
generator()->GenerateForNonPersistentNotification(
origin(), different_tag, kNonPersistentNotificationId));
}
// The persistent or non-persistent notification id will impact the generated
// notification id when the tag is empty.
TEST_F(NotificationIdGeneratorTest, DifferentIds) {
NotificationIdGenerator second_generator(browser_context(),
kRenderProcessId + 1);
// Persistent notifications.
EXPECT_NE(
generator()->GenerateForPersistentNotification(
origin(), "" /* tag */, kPersistentNotificationId),
generator()->GenerateForPersistentNotification(
origin(), "" /* tag */, kPersistentNotificationId + 1));
// Non-persistent notifications.
EXPECT_NE(
generator()->GenerateForNonPersistentNotification(
origin(), "" /* tag */, kNonPersistentNotificationId),
generator()->GenerateForNonPersistentNotification(
origin(), "" /* tag */, kNonPersistentNotificationId + 1));
// Non-persistent when a tag is being used.
EXPECT_EQ(
generator()->GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId),
second_generator.GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId));
}
// Using a numeric tag that could resemble a persistent notification id should
// not be equal to a notification without a tag, but with that id.
TEST_F(NotificationIdGeneratorTest, NumericTagAmbiguity) {
// Persistent notifications.
EXPECT_NE(
generator()->GenerateForPersistentNotification(
origin(),
base::Int64ToString(kPersistentNotificationId),
kPersistentNotificationId),
generator()->GenerateForPersistentNotification(
origin(), "" /* tag */, kPersistentNotificationId));
// Non-persistent notifications.
EXPECT_NE(
generator()->GenerateForNonPersistentNotification(
origin(),
base::IntToString(kNonPersistentNotificationId),
kNonPersistentNotificationId),
generator()->GenerateForNonPersistentNotification(
origin(), "" /* tag */, kNonPersistentNotificationId));
}
// Using port numbers and a tag which, when concatenated, could end up being
// equal to each other if origins stop ending with slashes.
TEST_F(NotificationIdGeneratorTest, OriginPortAmbiguity) {
GURL origin_805("https://example.com:805");
GURL origin_8051("https://example.com:8051");
// Persistent notifications.
EXPECT_NE(
generator()->GenerateForPersistentNotification(
origin_805, "17", kPersistentNotificationId),
generator()->GenerateForPersistentNotification(
origin_8051, "7", kPersistentNotificationId));
// Non-persistent notifications.
EXPECT_NE(
generator()->GenerateForNonPersistentNotification(
origin_805, "17", kNonPersistentNotificationId),
generator()->GenerateForNonPersistentNotification(
origin_8051, "7", kNonPersistentNotificationId));
}
// -----------------------------------------------------------------------------
// Persistent notifications
//
// Tests covering the logic specific to persistent notifications. This kind of
// notification does not care about the renderer process that created them.
TEST_F(NotificationIdGeneratorTest, PersistentDifferentRenderProcessIds) {
NotificationIdGenerator second_generator(browser_context(),
kRenderProcessId + 1);
EXPECT_EQ(
generator()->GenerateForPersistentNotification(
origin(), kExampleTag, kPersistentNotificationId),
second_generator.GenerateForPersistentNotification(
origin(), kExampleTag, kPersistentNotificationId));
EXPECT_EQ(
generator()->GenerateForPersistentNotification(
origin(), "" /* tag */, kPersistentNotificationId),
second_generator.GenerateForPersistentNotification(
origin(), "" /* tag */, kPersistentNotificationId));
}
// -----------------------------------------------------------------------------
// Non-persistent notifications
//
// Tests covering the logic specific to non-persistent notifications. This kind
// of notification cares about the renderer process they were created by when
// the notification does not have a tag, since multiple renderers would restart
// the count for non-persistent notification ids.
TEST_F(NotificationIdGeneratorTest, NonPersistentDifferentRenderProcessIds) {
NotificationIdGenerator second_generator(browser_context(),
kRenderProcessId + 1);
EXPECT_EQ(
generator()->GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId),
second_generator.GenerateForNonPersistentNotification(
origin(), kExampleTag, kNonPersistentNotificationId));
EXPECT_NE(
generator()->GenerateForNonPersistentNotification(
origin(), "" /* tag */, kNonPersistentNotificationId),
second_generator.GenerateForNonPersistentNotification(
origin(), "" /* tag */, kNonPersistentNotificationId));
}
// Concatenation of the render process id and the non-persistent notification
// id should not result in the generation of a duplicated notification id.
TEST_F(NotificationIdGeneratorTest, NonPersistentRenderProcessIdAmbiguity) {
NotificationIdGenerator generator_rpi_5(browser_context(), 5);
NotificationIdGenerator generator_rpi_51(browser_context(), 51);
EXPECT_NE(
generator_rpi_5.GenerateForNonPersistentNotification(
origin(), "" /* tag */, 1337 /* non_persistent_notification_id */),
generator_rpi_51.GenerateForNonPersistentNotification(
origin(), "" /* tag */, 337 /* non_persistent_notification_id */));
}
} // namespace
} // namespace content