blob: 72a72002ec3ac22dd8ce8e5d57fd96aaf857cbd9 [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 "third_party/blink/public/common/frame/user_activation_state.h"
#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
class UserActivationStateTest : public testing::Test {
public:
void SetUp() override {
time_overrides_ = std::make_unique<base::subtle::ScopedTimeClockOverrides>(
nullptr, &UserActivationStateTest::Now, nullptr);
}
static base::TimeTicks Now() {
now_ticks_ += base::TimeDelta::FromMilliseconds(1);
return now_ticks_;
}
static void AdvanceClock(base::TimeDelta time_delta) {
now_ticks_ += time_delta;
}
private:
static base::TimeTicks now_ticks_;
std::unique_ptr<base::subtle::ScopedTimeClockOverrides> time_overrides_;
};
// static
base::TimeTicks UserActivationStateTest::now_ticks_;
TEST_F(UserActivationStateTest, ConsumptionTest) {
UserActivationState user_activation_state;
// Initially both sticky and transient bits are unset, and consumption
// attempts fail.
EXPECT_FALSE(user_activation_state.HasBeenActive());
EXPECT_FALSE(user_activation_state.IsActive());
EXPECT_FALSE(user_activation_state.ConsumeIfActive());
EXPECT_FALSE(user_activation_state.ConsumeIfActive());
user_activation_state.Activate(
mojom::blink::UserActivationNotificationType::kTest);
// After activation, both sticky and transient bits are set, and consumption
// attempt succeeds once.
EXPECT_TRUE(user_activation_state.HasBeenActive());
EXPECT_TRUE(user_activation_state.IsActive());
EXPECT_TRUE(user_activation_state.ConsumeIfActive());
EXPECT_FALSE(user_activation_state.ConsumeIfActive());
// After successful consumption, only the transient bit gets reset, and
// further consumption attempts fail.
EXPECT_TRUE(user_activation_state.HasBeenActive());
EXPECT_FALSE(user_activation_state.IsActive());
EXPECT_FALSE(user_activation_state.ConsumeIfActive());
EXPECT_FALSE(user_activation_state.ConsumeIfActive());
}
TEST_F(UserActivationStateTest, ExpirationTest) {
UserActivationState user_activation_state;
user_activation_state.Activate(
mojom::blink::UserActivationNotificationType::kTest);
// Right before activation expiry, both bits remain set.
AdvanceClock(base::TimeDelta::FromMilliseconds(4995));
EXPECT_TRUE(user_activation_state.HasBeenActive());
EXPECT_TRUE(user_activation_state.IsActive());
// Right after activation expiry, only the transient bit gets reset.
AdvanceClock(base::TimeDelta::FromMilliseconds(10));
EXPECT_TRUE(user_activation_state.HasBeenActive());
EXPECT_FALSE(user_activation_state.IsActive());
}
TEST_F(UserActivationStateTest, ClearingTest) {
UserActivationState user_activation_state;
user_activation_state.Activate(
mojom::blink::UserActivationNotificationType::kTest);
EXPECT_TRUE(user_activation_state.HasBeenActive());
EXPECT_TRUE(user_activation_state.IsActive());
user_activation_state.Clear();
EXPECT_FALSE(user_activation_state.HasBeenActive());
EXPECT_FALSE(user_activation_state.IsActive());
}
TEST_F(UserActivationStateTest, ConsumptionPlusExpirationTest) {
UserActivationState user_activation_state;
// An activation is consumable before expiry.
user_activation_state.Activate(
mojom::blink::UserActivationNotificationType::kTest);
AdvanceClock(base::TimeDelta::FromMilliseconds(900));
EXPECT_TRUE(user_activation_state.ConsumeIfActive());
// An activation is not consumable after expiry.
user_activation_state.Activate(
mojom::blink::UserActivationNotificationType::kTest);
AdvanceClock(base::TimeDelta::FromSeconds(5));
EXPECT_FALSE(user_activation_state.ConsumeIfActive());
// Consecutive activations within expiry is consumable only once.
user_activation_state.Activate(
mojom::blink::UserActivationNotificationType::kTest);
AdvanceClock(base::TimeDelta::FromMilliseconds(900));
user_activation_state.Activate(
mojom::blink::UserActivationNotificationType::kTest);
EXPECT_TRUE(user_activation_state.ConsumeIfActive());
EXPECT_FALSE(user_activation_state.ConsumeIfActive());
// Non-consecutive activations within expiry is consumable separately.
user_activation_state.Activate(
mojom::blink::UserActivationNotificationType::kTest);
EXPECT_TRUE(user_activation_state.ConsumeIfActive());
AdvanceClock(base::TimeDelta::FromSeconds(900));
user_activation_state.Activate(
mojom::blink::UserActivationNotificationType::kTest);
EXPECT_TRUE(user_activation_state.ConsumeIfActive());
}
TEST_F(UserActivationStateTest, TransferBooleanTest) {
UserActivationState source;
UserActivationState target;
// Transfer from inactive source to inactive target.
source.Clear();
target.Clear();
target.TransferFrom(source);
EXPECT_FALSE(source.HasBeenActive());
EXPECT_FALSE(source.IsActive());
EXPECT_FALSE(target.HasBeenActive());
EXPECT_FALSE(target.IsActive());
// Transfer from inactive source to active target.
source.Clear();
target.Activate(mojom::blink::UserActivationNotificationType::kTest);
target.TransferFrom(source);
EXPECT_FALSE(source.HasBeenActive());
EXPECT_FALSE(source.IsActive());
EXPECT_TRUE(target.HasBeenActive());
EXPECT_TRUE(target.IsActive());
// Transfer from active source to inactive target.
source.Activate(mojom::blink::UserActivationNotificationType::kTest);
target.Clear();
target.TransferFrom(source);
EXPECT_FALSE(source.HasBeenActive());
EXPECT_FALSE(source.IsActive());
EXPECT_TRUE(target.HasBeenActive());
EXPECT_TRUE(target.IsActive());
// Transfer from active source to active target.
source.Activate(mojom::blink::UserActivationNotificationType::kTest);
target.Activate(mojom::blink::UserActivationNotificationType::kTest);
target.TransferFrom(source);
EXPECT_FALSE(source.HasBeenActive());
EXPECT_FALSE(source.IsActive());
EXPECT_TRUE(target.HasBeenActive());
EXPECT_TRUE(target.IsActive());
}
TEST_F(UserActivationStateTest, TransferExpirationTest) {
UserActivationState source;
UserActivationState target;
// Source activated before target.
source.Activate(mojom::blink::UserActivationNotificationType::kTest);
AdvanceClock(base::TimeDelta::FromSeconds(1));
target.Activate(mojom::blink::UserActivationNotificationType::kTest);
target.TransferFrom(source);
AdvanceClock(base::TimeDelta::FromMilliseconds(4995));
EXPECT_TRUE(target.IsActive());
AdvanceClock(base::TimeDelta::FromMilliseconds(10));
EXPECT_FALSE(target.IsActive());
// Source activated after target.
target.Activate(mojom::blink::UserActivationNotificationType::kTest);
AdvanceClock(base::TimeDelta::FromSeconds(1));
source.Activate(mojom::blink::UserActivationNotificationType::kTest);
target.TransferFrom(source);
AdvanceClock(base::TimeDelta::FromMilliseconds(4995));
EXPECT_TRUE(target.IsActive());
AdvanceClock(base::TimeDelta::FromMilliseconds(10));
EXPECT_FALSE(target.IsActive());
// Source and target activated at the same time.
source.Activate(mojom::blink::UserActivationNotificationType::kTest);
target.Activate(mojom::blink::UserActivationNotificationType::kTest);
target.TransferFrom(source);
AdvanceClock(base::TimeDelta::FromMilliseconds(4995));
EXPECT_TRUE(target.IsActive());
AdvanceClock(base::TimeDelta::FromMilliseconds(10));
EXPECT_FALSE(target.IsActive());
// Inactive target received transfer from active source after a delay.
source.Activate(mojom::blink::UserActivationNotificationType::kTest);
target.Clear();
AdvanceClock(base::TimeDelta::FromSeconds(1));
target.TransferFrom(source);
AdvanceClock(base::TimeDelta::FromMilliseconds(3995));
EXPECT_TRUE(target.IsActive());
AdvanceClock(base::TimeDelta::FromMilliseconds(10));
EXPECT_FALSE(target.IsActive());
// Active target received transfer from inactive source after a delay.
source.Clear();
target.Activate(mojom::blink::UserActivationNotificationType::kTest);
AdvanceClock(base::TimeDelta::FromSeconds(1));
target.TransferFrom(source);
AdvanceClock(base::TimeDelta::FromMilliseconds(3995));
EXPECT_TRUE(target.IsActive());
AdvanceClock(base::TimeDelta::FromMilliseconds(10));
EXPECT_FALSE(target.IsActive());
}
} // namespace blink