// Copyright 2017 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in LICENSE file. #include "base/numerics/safe_conversions.h" #include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/core/testing/sim/sim_request.h" #include "third_party/blink/renderer/core/testing/sim/sim_test.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" #include "third_party/blink/renderer/platform/wtf/wtf_size_t.h" AnyOf; ElementsAre; namespace blink { // When a page is backgrounded this is the absolute smallest amount of time // that can elapse between timer wake-ups. constexpr auto kDefaultThrottledWakeUpInterval = …; // This test suite relies on messages being posted to the console. In order to // be resilient against messages not posted by this specific test suite, a small // prefix is used to allowed filtering. constexpr char kTestConsoleMessagePrefix[] = …; // A SimTest with mock time. class ThrottlingTestBase : public SimTest { … }; class DisableBackgroundThrottlingIsRespectedTest : public ThrottlingTestBase, private ScopedTimerThrottlingForBackgroundTabsForTest { … }; TEST_F(DisableBackgroundThrottlingIsRespectedTest, DisableBackgroundThrottlingIsRespected) { … } class BackgroundPageThrottlingTest : public ThrottlingTestBase { … }; TEST_F(BackgroundPageThrottlingTest, TimersThrottledInBackgroundPage) { … } // Verify the execution time of non-nested timers on a hidden page. // - setTimeout(..., 0) and setTimeout(..., -1) schedule their callback after // 1ms. The 1 ms delay exists for historical reasons crbug.com/402694. // - setTimeout(..., 5) schedules its callback at the next aligned time TEST_F(BackgroundPageThrottlingTest, WithoutNesting) { … } // Verify that on a hidden page, a timer created with setTimeout(..., 0) is // throttled after 5 nesting levels. TEST_F(BackgroundPageThrottlingTest, NestedSetTimeoutZero) { … } // Verify that in a hidden page, a timer created with setInterval(..., 0) is // throttled after 5 nesting levels. TEST_F(BackgroundPageThrottlingTest, NestedSetIntervalZero) { … } class AbortSignalTimeoutThrottlingTest : public BackgroundPageThrottlingTest { … }; TEST_F(AbortSignalTimeoutThrottlingTest, TimeoutsThrottledInBackgroundPage) { … } TEST_F(AbortSignalTimeoutThrottlingTest, ZeroMsTimersNotThrottled) { … } namespace { class IntensiveWakeUpThrottlingTest : public ThrottlingTestBase { … }; // Use to install a function that does not actually communicate with the user. constexpr char kCommunicationNop[] = …; // Use to install a function that will communicate with the user via title // update. constexpr char kCommunicateThroughTitleScript[] = …; // Use to install a function that will communicate with the user via favicon // update. constexpr char kCommunicateThroughFavisonScript[] = …; // A script that schedules a timer task which logs to the console. The timer // task has a high nesting level and its timeout is not aligned on the intensive // wake up throttling interval. constexpr char kLongUnalignedTimerScriptTemplate[] = …; // A time delta that matches the delay in the above script. constexpr base::TimeDelta kLongUnalignedTimerDelay = …; // Builds a page that waits 5 minutes and then creates a timer that reschedules // itself 50 times with 10 ms delay. The timer task logs |console_message| to // the console and invokes maybeCommunicateInBackground(). The caller must // provide the definition of maybeCommunicateInBackground() via // |communicate_script|. String BuildRepeatingTimerPage(const char* console_message, const char* communicate_script) { … } } // namespace // Verify that a main frame timer that reposts itself with a 10 ms timeout runs // once every minute. TEST_F(IntensiveWakeUpThrottlingTest, MainFrameTimer_ShortTimeout) { … } // Verify that a main frame timer that reposts itself with a 10 ms timeout runs // once every |kDefaultThrottledWakeUpInterval| after the first confirmed page // communication through title update. TEST_F(IntensiveWakeUpThrottlingTest, MainFrameTimer_ShortTimeout_TitleUpdate) { … } // Verify that a main frame timer that reposts itself with a 10 ms timeout runs // once every |kDefaultThrottledWakeUpInterval| after the first confirmed page // communication through favicon update. TEST_F(IntensiveWakeUpThrottlingTest, MainFrameTimer_ShortTimeout_FaviconUpdate) { … } // Verify that a same-origin subframe timer that reposts itself with a 10 ms // timeout runs once every minute. TEST_F(IntensiveWakeUpThrottlingTest, SameOriginSubFrameTimer_ShortTimeout) { … } // Verify that a cross-origin subframe timer that reposts itself with a 10 ms // timeout runs once every minute. TEST_F(IntensiveWakeUpThrottlingTest, CrossOriginSubFrameTimer_ShortTimeout) { … } // Verify that a main frame timer with a long timeout runs at the desired run // time when there is no other recent timer wake up. TEST_F(IntensiveWakeUpThrottlingTest, MainFrameTimer_LongUnalignedTimeout) { … } // Verify that a same-origin subframe timer with a long timeout runs at the // desired run time when there is no other recent timer wake up. TEST_F(IntensiveWakeUpThrottlingTest, SameOriginSubFrameTimer_LongUnalignedTimeout) { … } // Verify that a cross-origin subframe timer with a long timeout runs at an // aligned time, even when there is no other recent timer wake up (in a // same-origin frame, it would have run at the desired time). TEST_F(IntensiveWakeUpThrottlingTest, CrossOriginSubFrameTimer_LongUnalignedTimeout) { … } // Verify that if both the main frame and a cross-origin frame schedule a timer // with a long unaligned delay, the main frame timer runs at the desired time // (because there was no recent same-origin wake up) while the cross-origin // timer runs at an aligned time. TEST_F(IntensiveWakeUpThrottlingTest, MainFrameAndCrossOriginSubFrameTimer_LongUnalignedTimeout) { … } } // namespace blink