[go: nahoru, domu]

blob: a7d3cb2df023b3a4869bb3a86207847ff714c44c [file] [log] [blame]
// Copyright 2016 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 "platform/scheduler/renderer/web_frame_scheduler_impl.h"
#include <memory>
#include "base/callback.h"
#include "base/memory/ptr_util.h"
#include "base/test/simple_test_tick_clock.h"
#include "components/viz/test/ordered_simple_task_runner.h"
#include "platform/WebTaskRunner.h"
#include "platform/runtime_enabled_features.h"
#include "platform/scheduler/base/test_time_source.h"
#include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h"
#include "platform/scheduler/renderer/renderer_scheduler_impl.h"
#include "platform/scheduler/renderer/web_view_scheduler_impl.h"
#include "public/platform/WebTraceLocation.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
namespace scheduler {
class WebFrameSchedulerImplTest : public ::testing::Test {
public:
WebFrameSchedulerImplTest() {}
~WebFrameSchedulerImplTest() override {}
void SetUp() override {
clock_.reset(new base::SimpleTestTickClock());
clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
mock_task_runner_ =
base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(clock_.get(), true);
delegate_ = SchedulerTqmDelegateForTest::Create(
mock_task_runner_, base::WrapUnique(new TestTimeSource(clock_.get())));
scheduler_.reset(new RendererSchedulerImpl(delegate_));
web_view_scheduler_.reset(
new WebViewSchedulerImpl(nullptr, nullptr, scheduler_.get(), false));
web_frame_scheduler_ =
web_view_scheduler_->CreateWebFrameSchedulerImpl(nullptr);
}
void TearDown() override {
web_frame_scheduler_.reset();
web_view_scheduler_.reset();
scheduler_->Shutdown();
scheduler_.reset();
}
std::unique_ptr<base::SimpleTestTickClock> clock_;
scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
scoped_refptr<SchedulerTqmDelegate> delegate_;
std::unique_ptr<RendererSchedulerImpl> scheduler_;
std::unique_ptr<WebViewSchedulerImpl> web_view_scheduler_;
std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler_;
};
namespace {
class MockThrottlingObserver final : public WebFrameScheduler::Observer {
public:
MockThrottlingObserver() : throttled_count_(0u), not_throttled_count_(0u) {}
void CheckObserverState(size_t throttled_count_expectation,
size_t not_throttled_count_expectation) {
EXPECT_EQ(throttled_count_expectation, throttled_count_);
EXPECT_EQ(not_throttled_count_expectation, not_throttled_count_);
}
// WebFrameScheduler::Observer.
void OnThrottlingStateChanged(
WebFrameScheduler::ThrottlingState state) override {
switch (state) {
case WebFrameScheduler::ThrottlingState::kThrottled:
throttled_count_++;
break;
case WebFrameScheduler::ThrottlingState::kNotThrottled:
not_throttled_count_++;
break;
// We should not have another state, and compiler checks it.
}
}
private:
size_t throttled_count_;
size_t not_throttled_count_;
};
void RunRepeatingTask(RefPtr<WebTaskRunner> task_runner, int* run_count);
WTF::Closure MakeRepeatingTask(RefPtr<blink::WebTaskRunner> task_runner,
int* run_count) {
return WTF::Bind(&RunRepeatingTask, WTF::Passed(std::move(task_runner)),
WTF::Unretained(run_count));
}
void RunRepeatingTask(RefPtr<WebTaskRunner> task_runner, int* run_count) {
++*run_count;
WebTaskRunner* task_runner_ptr = task_runner.Get();
task_runner_ptr->PostDelayedTask(
BLINK_FROM_HERE, MakeRepeatingTask(std::move(task_runner), run_count),
TimeDelta::FromMilliseconds(1));
}
void IncrementCounter(int* counter) {
++*counter;
}
} // namespace
TEST_F(WebFrameSchedulerImplTest, RepeatingTimer_PageInForeground) {
RuntimeEnabledFeatures::SetTimerThrottlingForHiddenFramesEnabled(true);
int run_count = 0;
web_frame_scheduler_->ThrottleableTaskRunner()->PostDelayedTask(
BLINK_FROM_HERE,
MakeRepeatingTask(web_frame_scheduler_->ThrottleableTaskRunner(),
&run_count),
TimeDelta::FromMilliseconds(1));
mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1000, run_count);
}
TEST_F(WebFrameSchedulerImplTest, RepeatingTimer_PageInBackground) {
RuntimeEnabledFeatures::SetTimerThrottlingForHiddenFramesEnabled(true);
web_view_scheduler_->SetPageVisible(false);
int run_count = 0;
web_frame_scheduler_->ThrottleableTaskRunner()->PostDelayedTask(
BLINK_FROM_HERE,
MakeRepeatingTask(web_frame_scheduler_->ThrottleableTaskRunner(),
&run_count),
TimeDelta::FromMilliseconds(1));
mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1, run_count);
}
TEST_F(WebFrameSchedulerImplTest, RepeatingTimer_FrameHidden_SameOrigin) {
RuntimeEnabledFeatures::SetTimerThrottlingForHiddenFramesEnabled(true);
web_frame_scheduler_->SetFrameVisible(false);
int run_count = 0;
web_frame_scheduler_->ThrottleableTaskRunner()->PostDelayedTask(
BLINK_FROM_HERE,
MakeRepeatingTask(web_frame_scheduler_->ThrottleableTaskRunner(),
&run_count),
TimeDelta::FromMilliseconds(1));
mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1000, run_count);
}
TEST_F(WebFrameSchedulerImplTest, RepeatingTimer_FrameVisible_CrossOrigin) {
RuntimeEnabledFeatures::SetTimerThrottlingForHiddenFramesEnabled(true);
web_frame_scheduler_->SetFrameVisible(true);
web_frame_scheduler_->SetCrossOrigin(true);
int run_count = 0;
web_frame_scheduler_->ThrottleableTaskRunner()->PostDelayedTask(
BLINK_FROM_HERE,
MakeRepeatingTask(web_frame_scheduler_->ThrottleableTaskRunner(),
&run_count),
TimeDelta::FromMilliseconds(1));
mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1000, run_count);
}
TEST_F(WebFrameSchedulerImplTest, RepeatingTimer_FrameHidden_CrossOrigin) {
RuntimeEnabledFeatures::SetTimerThrottlingForHiddenFramesEnabled(true);
web_frame_scheduler_->SetFrameVisible(false);
web_frame_scheduler_->SetCrossOrigin(true);
int run_count = 0;
web_frame_scheduler_->ThrottleableTaskRunner()->PostDelayedTask(
BLINK_FROM_HERE,
MakeRepeatingTask(web_frame_scheduler_->ThrottleableTaskRunner(),
&run_count),
TimeDelta::FromMilliseconds(1));
mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1, run_count);
}
TEST_F(WebFrameSchedulerImplTest, PageInBackground_ThrottlingDisabled) {
RuntimeEnabledFeatures::SetTimerThrottlingForHiddenFramesEnabled(false);
web_view_scheduler_->SetPageVisible(false);
int run_count = 0;
web_frame_scheduler_->ThrottleableTaskRunner()->PostDelayedTask(
BLINK_FROM_HERE,
MakeRepeatingTask(web_frame_scheduler_->ThrottleableTaskRunner(),
&run_count),
TimeDelta::FromMilliseconds(1));
mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1, run_count);
}
TEST_F(WebFrameSchedulerImplTest,
RepeatingTimer_FrameHidden_CrossOrigin_ThrottlingDisabled) {
RuntimeEnabledFeatures::SetTimerThrottlingForHiddenFramesEnabled(false);
web_frame_scheduler_->SetFrameVisible(false);
web_frame_scheduler_->SetCrossOrigin(true);
int run_count = 0;
web_frame_scheduler_->ThrottleableTaskRunner()->PostDelayedTask(
BLINK_FROM_HERE,
MakeRepeatingTask(web_frame_scheduler_->ThrottleableTaskRunner(),
&run_count),
TimeDelta::FromMilliseconds(1));
mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1000, run_count);
}
TEST_F(WebFrameSchedulerImplTest, PauseAndResume) {
int counter = 0;
web_frame_scheduler_->LoadingTaskRunner()->PostTask(
BLINK_FROM_HERE, WTF::Bind(&IncrementCounter, WTF::Unretained(&counter)));
web_frame_scheduler_->ThrottleableTaskRunner()->PostTask(
BLINK_FROM_HERE, WTF::Bind(&IncrementCounter, WTF::Unretained(&counter)));
web_frame_scheduler_->DeferrableTaskRunner()->PostTask(
BLINK_FROM_HERE, WTF::Bind(&IncrementCounter, WTF::Unretained(&counter)));
web_frame_scheduler_->PausableTaskRunner()->PostTask(
BLINK_FROM_HERE, WTF::Bind(&IncrementCounter, WTF::Unretained(&counter)));
web_frame_scheduler_->UnpausableTaskRunner()->PostTask(
BLINK_FROM_HERE, WTF::Bind(&IncrementCounter, WTF::Unretained(&counter)));
web_frame_scheduler_->SetPaused(true);
EXPECT_EQ(0, counter);
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(1, counter);
web_frame_scheduler_->SetPaused(false);
EXPECT_EQ(1, counter);
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(5, counter);
}
// Tests if throttling observer interfaces work.
TEST_F(WebFrameSchedulerImplTest, ThrottlingObserver) {
std::unique_ptr<MockThrottlingObserver> observer =
base::MakeUnique<MockThrottlingObserver>();
size_t throttled_count = 0u;
size_t not_throttled_count = 0u;
observer->CheckObserverState(throttled_count, not_throttled_count);
web_frame_scheduler_->AddThrottlingObserver(
WebFrameScheduler::ObserverType::kLoader, observer.get());
// Initial state should be synchronously notified here.
// We assume kNotThrottled is notified as an initial state, but it could
// depend on implementation details and can be changed.
observer->CheckObserverState(throttled_count, ++not_throttled_count);
// Once the page gets to be invisible, it should notify the observer of
// kThrottled synchronously.
web_view_scheduler_->SetPageVisible(false);
observer->CheckObserverState(++throttled_count, not_throttled_count);
// Going back to visible state should notify the observer of kNotThrottled
// synchronously.
web_view_scheduler_->SetPageVisible(true);
observer->CheckObserverState(throttled_count, ++not_throttled_count);
// Remove from the observer list, and see if any other callback should not be
// invoked when the condition is changed.
web_frame_scheduler_->RemoveThrottlingObserver(
WebFrameScheduler::ObserverType::kLoader, observer.get());
web_view_scheduler_->SetPageVisible(false);
// Wait 100 secs virtually and run pending tasks just in case.
clock_->Advance(base::TimeDelta::FromSeconds(100));
mock_task_runner_->RunUntilIdle();
observer->CheckObserverState(throttled_count, not_throttled_count);
}
} // namespace scheduler
} // namespace blink