Commit 5c199801 authored by Alexander Timin's avatar Alexander Timin Committed by Commit Bot

[scheduler] Do not store page-level signals in FrameScheduler.

Make FrameScheduler ask PageScheduler for page-level metrics whenever it
needs them (also known as pull-approach).

We need to be careful to call PageScheduler::NotifyFrames each time when
a signal changes. However, this patch eliminated a bunch of incorrect
frame init when a page-level signal wasn't plumbed to a page.

Some signals are still saved in FrameScheduler for tracing purposes only
and renamed accordingly.

R=alexclarke@chromium.org,skyostil@chromium.org

Change-Id: I006713eac119b7619adf858beed3038b9914f274
Reviewed-on: https://chromium-review.googlesource.com/1069269
Commit-Queue: Alexander Timin <altimin@chromium.org>
Reviewed-by: default avatarAlex Clarke <alexclarke@chromium.org>
Cr-Commit-Position: refs/heads/master@{#561038}
parent 820f59a7
......@@ -118,21 +118,6 @@ FrameSchedulerImpl::FrameSchedulerImpl(
this,
&tracing_controller_,
VisibilityStateToString),
page_visibility_(kDefaultPageVisibility,
"FrameScheduler.PageVisibility",
this,
&tracing_controller_,
PageVisibilityStateToString),
page_frozen_(false,
"FrameScheduler.PageFrozen",
this,
&tracing_controller_,
FrozenStateToString),
keep_active_(main_thread_scheduler->SchedulerKeepActive(),
"FrameScheduler.KeepActive",
this,
&tracing_controller_,
KeepActiveStateToString),
frame_paused_(false,
"FrameScheduler.FramePaused",
this,
......@@ -157,6 +142,23 @@ FrameSchedulerImpl::FrameSchedulerImpl(
this,
&tracing_controller_,
YesNoStateToString),
page_frozen_for_tracing_(parent_page_scheduler_->IsFrozen(),
"FrameScheduler.PageFrozen",
this,
&tracing_controller_,
FrozenStateToString),
page_visibility_for_tracing_(parent_page_scheduler_->IsPageVisible()
? PageVisibilityState::kVisible
: PageVisibilityState::kHidden,
"FrameScheduler.PageVisibility",
this,
&tracing_controller_,
PageVisibilityStateToString),
page_keep_active_for_tracing_(parent_page_scheduler_->KeepActive(),
"FrameScheduler.KeepActive",
this,
&tracing_controller_,
KeepActiveStateToString),
weak_factory_(this) {}
namespace {
......@@ -239,7 +241,7 @@ void FrameSchedulerImpl::SetFrameVisible(bool frame_visible) {
return;
UMA_HISTOGRAM_BOOLEAN("RendererScheduler.IPC.FrameVisibility", frame_visible);
frame_visible_ = frame_visible;
UpdateThrottling();
UpdatePolicy();
}
bool FrameSchedulerImpl::IsFrameVisible() const {
......@@ -257,7 +259,7 @@ void FrameSchedulerImpl::SetCrossOrigin(bool cross_origin) {
} else {
frame_origin_type_ = FrameOriginType::kSameOriginFrame;
}
UpdateThrottling();
UpdatePolicy();
}
bool FrameSchedulerImpl::IsCrossOrigin() const {
......@@ -500,8 +502,7 @@ void FrameSchedulerImpl::DidCloseActiveConnection() {
void FrameSchedulerImpl::AsValueInto(
base::trace_event::TracedValue* state) const {
state->SetBoolean("frame_visible", frame_visible_);
state->SetBoolean("page_visible",
page_visibility_ == PageVisibilityState::kVisible);
state->SetBoolean("page_visible", parent_page_scheduler_->IsPageVisible());
state->SetBoolean("cross_origin", IsCrossOrigin());
state->SetString("frame_type",
frame_type_ == FrameScheduler::FrameType::kMainFrame
......@@ -541,19 +542,14 @@ void FrameSchedulerImpl::AsValueInto(
}
}
void FrameSchedulerImpl::SetPageVisibility(
void FrameSchedulerImpl::SetPageVisibilityForTracing(
PageVisibilityState page_visibility) {
DCHECK(parent_page_scheduler_);
if (page_visibility_ == page_visibility)
return;
page_visibility_ = page_visibility;
if (page_visibility_ == PageVisibilityState::kVisible)
page_frozen_ = false; // visible page must not be frozen.
UpdatePolicy();
page_visibility_for_tracing_ = page_visibility;
}
bool FrameSchedulerImpl::IsPageVisible() const {
return page_visibility_ == PageVisibilityState::kVisible;
return parent_page_scheduler_ ? parent_page_scheduler_->IsPageVisible()
: true;
}
void FrameSchedulerImpl::SetPaused(bool frame_paused) {
......@@ -565,15 +561,12 @@ void FrameSchedulerImpl::SetPaused(bool frame_paused) {
UpdatePolicy();
}
void FrameSchedulerImpl::SetPageFrozen(bool frozen) {
DCHECK(!frozen || page_visibility_ == PageVisibilityState::kHidden);
page_frozen_ = frozen;
UpdatePolicy();
void FrameSchedulerImpl::SetPageFrozenForTracing(bool frozen) {
page_frozen_for_tracing_ = frozen;
}
void FrameSchedulerImpl::SetKeepActive(bool keep_active) {
keep_active_ = keep_active;
UpdatePolicy();
void FrameSchedulerImpl::SetPageKeepActiveForTracing(bool keep_active) {
page_keep_active_for_tracing_ = keep_active;
}
void FrameSchedulerImpl::UpdatePolicy() {
......@@ -598,11 +591,13 @@ void FrameSchedulerImpl::UpdateQueuePolicy(
TaskQueue::QueueEnabledVoter* voter) {
if (!queue || !voter)
return;
DCHECK(parent_page_scheduler_);
bool queue_paused = frame_paused_ && queue->CanBePaused();
bool queue_frozen = page_frozen_ && queue->CanBeFrozen();
bool queue_frozen =
parent_page_scheduler_->IsFrozen() && queue->CanBeFrozen();
// Override freezing if keep-active is true.
if (queue_frozen && !queue->FreezeWhenKeepActive())
queue_frozen = !keep_active_;
queue_frozen = !parent_page_scheduler_->KeepActive();
voter->SetQueueEnabled(!queue_paused && !queue_frozen);
}
......@@ -620,8 +615,9 @@ FrameScheduler::ThrottlingState FrameSchedulerImpl::CalculateThrottlingState(
return FrameScheduler::ThrottlingState::kNotThrottled;
if (RuntimeEnabledFeatures::StopLoadingInBackgroundEnabled() &&
parent_page_scheduler_->IsFrozen() && !keep_active_) {
DCHECK(page_visibility_ == PageVisibilityState::kHidden);
parent_page_scheduler_->IsFrozen() &&
!parent_page_scheduler_->KeepActive()) {
DCHECK(!parent_page_scheduler_->IsPageVisible());
return FrameScheduler::ThrottlingState::kStopped;
}
if (type == ObserverType::kLoader &&
......@@ -647,7 +643,7 @@ FrameSchedulerImpl::OnActiveConnectionCreated() {
bool FrameSchedulerImpl::ShouldThrottleTimers() const {
if (parent_page_scheduler_ && parent_page_scheduler_->IsAudioPlaying())
return false;
if (page_visibility_ == PageVisibilityState::kHidden)
if (!parent_page_scheduler_->IsPageVisible())
return true;
return RuntimeEnabledFeatures::TimerThrottlingForHiddenFramesEnabled() &&
!frame_visible_ && IsCrossOrigin();
......
......@@ -66,8 +66,6 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
bool IsFrameVisible() const override;
bool IsPageVisible() const override;
void SetPaused(bool frame_paused) override;
void SetPageFrozen(bool) override;
void SetKeepActive(bool) override;
void SetCrossOrigin(bool cross_origin) override;
bool IsCrossOrigin() const override;
......@@ -88,7 +86,6 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
bool IsExemptFromBudgetBasedThrottling() const override;
scoped_refptr<base::sequence_manager::TaskQueue> ControlTaskQueue();
void SetPageVisibility(PageVisibilityState page_visibility);
void UpdatePolicy();
......@@ -96,6 +93,10 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
void OnTraceLogEnabled() { tracing_controller_.OnTraceLogEnabled(); }
void SetPageVisibilityForTracing(PageVisibilityState page_visibility);
void SetPageKeepActiveForTracing(bool keep_active);
void SetPageFrozenForTracing(bool frozen);
private:
friend class PageSchedulerImpl;
friend class main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest;
......@@ -177,10 +178,6 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
std::unordered_map<Observer*, ObserverType> throttling_observers_;
FrameScheduler::ThrottlingState throttling_state_;
TraceableState<bool, kTracingCategoryNameInfo> frame_visible_;
TraceableState<PageVisibilityState, kTracingCategoryNameInfo>
page_visibility_;
TraceableState<bool, kTracingCategoryNameInfo> page_frozen_;
TraceableState<bool, kTracingCategoryNameInfo> keep_active_;
TraceableState<bool, kTracingCategoryNameInfo> frame_paused_;
TraceableState<FrameOriginType, kTracingCategoryNameInfo> frame_origin_type_;
StateTracer<kTracingCategoryNameInfo> url_tracer_;
......@@ -191,6 +188,14 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
int active_connection_count_;
TraceableState<bool, kTracingCategoryNameInfo> has_active_connection_;
// These are the states of the Page.
// They should be accessed via GetPageScheduler()->SetPageState().
// they are here because we don't support page-level tracing yet.
TraceableState<bool, kTracingCategoryNameInfo> page_frozen_for_tracing_;
TraceableState<PageVisibilityState, kTracingCategoryNameInfo>
page_visibility_for_tracing_;
TraceableState<bool, kTracingCategoryNameInfo> page_keep_active_for_tracing_;
base::WeakPtrFactory<FrameSchedulerImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(FrameSchedulerImpl);
......
......@@ -10,6 +10,7 @@
#include "base/location.h"
#include "base/test/simple_test_tick_clock.h"
#include "components/viz/test/ordered_simple_task_runner.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
......@@ -19,6 +20,7 @@
#include "third_party/blink/renderer/platform/web_task_runner.h"
using base::sequence_manager::TaskQueue;
using testing::UnorderedElementsAre;
namespace blink {
namespace scheduler {
......@@ -152,6 +154,11 @@ void IncrementCounter(int* counter) {
++*counter;
}
void RecordQueueName(const scoped_refptr<TaskQueue> task_queue,
std::vector<std::string>* tasks) {
tasks->push_back(task_queue->GetName());
}
} // namespace
// Throttleable task queue is initialized lazily, so there're two scenarios:
......@@ -312,15 +319,15 @@ TEST_F(FrameSchedulerImplTest, PageFreezeAndUnfreezeFlagEnabled) {
UnpausableTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
frame_scheduler_->SetPageVisibility(PageVisibilityState::kHidden);
frame_scheduler_->SetPageFrozen(true);
page_scheduler_->SetPageVisible(false);
page_scheduler_->SetPageFrozen(true);
EXPECT_EQ(0, counter);
mock_task_runner_->RunUntilIdle();
// unpausable tasks continue to run.
EXPECT_EQ(1, counter);
frame_scheduler_->SetPageFrozen(false);
page_scheduler_->SetPageFrozen(false);
EXPECT_EQ(1, counter);
mock_task_runner_->RunUntilIdle();
......@@ -342,15 +349,15 @@ TEST_F(FrameSchedulerImplTest, PageFreezeAndUnfreezeFlagDisabled) {
UnpausableTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
frame_scheduler_->SetPageVisibility(PageVisibilityState::kHidden);
frame_scheduler_->SetPageFrozen(true);
page_scheduler_->SetPageVisible(false);
page_scheduler_->SetPageFrozen(true);
EXPECT_EQ(0, counter);
mock_task_runner_->RunUntilIdle();
// throttleable tasks are frozen, other tasks continue to run.
EXPECT_EQ(4, counter);
frame_scheduler_->SetPageFrozen(false);
page_scheduler_->SetPageFrozen(false);
EXPECT_EQ(4, counter);
mock_task_runner_->RunUntilIdle();
......@@ -360,46 +367,60 @@ TEST_F(FrameSchedulerImplTest, PageFreezeAndUnfreezeFlagDisabled) {
TEST_F(FrameSchedulerImplTest, PageFreezeWithKeepActive) {
ScopedStopLoadingInBackgroundForTest stop_loading_enabler(true);
ScopedStopNonTimersInBackgroundForTest stop_non_timers_enabler(false);
int counter = 0;
std::vector<std::string> tasks;
LoadingTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
FROM_HERE, base::BindOnce(&RecordQueueName, LoadingTaskQueue(), &tasks));
ThrottleableTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
FROM_HERE,
base::BindOnce(&RecordQueueName, ThrottleableTaskQueue(), &tasks));
DeferrableTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
FROM_HERE,
base::BindOnce(&RecordQueueName, DeferrableTaskQueue(), &tasks));
PausableTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
FROM_HERE, base::BindOnce(&RecordQueueName, PausableTaskQueue(), &tasks));
UnpausableTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
FROM_HERE,
base::BindOnce(&RecordQueueName, UnpausableTaskQueue(), &tasks));
frame_scheduler_->SetKeepActive(true); // say we have a Service Worker
frame_scheduler_->SetPageVisibility(PageVisibilityState::kHidden);
frame_scheduler_->SetPageFrozen(true);
page_scheduler_->SetKeepActive(true); // say we have a Service Worker
page_scheduler_->SetPageVisible(false);
page_scheduler_->SetPageFrozen(true);
EXPECT_EQ(0, counter);
EXPECT_THAT(tasks, UnorderedElementsAre());
mock_task_runner_->RunUntilIdle();
// Everything runs except throttleable tasks (timers)
EXPECT_EQ(4, counter);
EXPECT_THAT(tasks, UnorderedElementsAre(
std::string(LoadingTaskQueue()->GetName()),
std::string(DeferrableTaskQueue()->GetName()),
std::string(PausableTaskQueue()->GetName()),
std::string(UnpausableTaskQueue()->GetName())));
tasks.clear();
LoadingTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
FROM_HERE, base::BindOnce(&RecordQueueName, LoadingTaskQueue(), &tasks));
EXPECT_EQ(4, counter);
EXPECT_THAT(tasks, UnorderedElementsAre());
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(5, counter); // loading task runs
// loading task runs
EXPECT_THAT(tasks,
UnorderedElementsAre(std::string(LoadingTaskQueue()->GetName())));
tasks.clear();
LoadingTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
FROM_HERE, base::BindOnce(&RecordQueueName, LoadingTaskQueue(), &tasks));
// KeepActive is false when Service Worker stops.
frame_scheduler_->SetKeepActive(false);
EXPECT_EQ(5, counter);
page_scheduler_->SetKeepActive(false);
EXPECT_THAT(tasks, UnorderedElementsAre());
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(5, counter); // loading task does not run
EXPECT_THAT(tasks, UnorderedElementsAre()); // loading task does not run
frame_scheduler_->SetKeepActive(true);
EXPECT_EQ(5, counter);
tasks.clear();
page_scheduler_->SetKeepActive(true);
EXPECT_THAT(tasks, UnorderedElementsAre());
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(6, counter); // loading task runs
// loading task runs
EXPECT_THAT(tasks,
UnorderedElementsAre(std::string(LoadingTaskQueue()->GetName())));
}
TEST_F(FrameSchedulerImplTest, PageFreezeAndPageVisible) {
......@@ -417,15 +438,15 @@ TEST_F(FrameSchedulerImplTest, PageFreezeAndPageVisible) {
UnpausableTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
frame_scheduler_->SetPageVisibility(PageVisibilityState::kHidden);
frame_scheduler_->SetPageFrozen(true);
page_scheduler_->SetPageVisible(false);
page_scheduler_->SetPageFrozen(true);
EXPECT_EQ(0, counter);
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(1, counter);
// Making the page visible should cause frozen queues to resume.
frame_scheduler_->SetPageVisibility(PageVisibilityState::kVisible);
page_scheduler_->SetPageVisible(true);
EXPECT_EQ(1, counter);
mock_task_runner_->RunUntilIdle();
......
......@@ -114,12 +114,13 @@ PageSchedulerImpl::PageSchedulerImpl(
nested_runloop_(false),
is_main_frame_local_(false),
is_throttled_(false),
keep_active_(false),
background_time_budget_pool_(nullptr),
delegate_(delegate),
weak_factory_(this) {
main_thread_scheduler->AddPageScheduler(this);
on_page_throttled_closure_.Reset(base::BindRepeating(
&PageSchedulerImpl::OnPageThrottled, base::Unretained(this)));
do_throttle_page_callback_.Reset(base::BindRepeating(
&PageSchedulerImpl::DoThrottlePage, base::Unretained(this)));
on_audio_silent_closure_.Reset(base::BindRepeating(
&PageSchedulerImpl::OnAudioSilent, base::Unretained(this)));
}
......@@ -144,35 +145,52 @@ void PageSchedulerImpl::SetPageVisible(bool page_visible) {
if (disable_background_timer_throttling_ ||
page_visibility_ == page_visibility)
return;
page_visibility_ = page_visibility;
// Visible pages should not be frozen.
if (page_visibility_ == PageVisibilityState::kVisible) {
is_throttled_ = false;
if (is_frozen_)
SetPageFrozen(false);
}
if (page_visibility_ == PageVisibilityState::kVisible)
SetPageFrozenImpl(false, NotificationPolicy::kDoNotNotifyFrames);
for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_)
frame_scheduler->SetPageVisibility(page_visibility_);
frame_scheduler->SetPageVisibilityForTracing(page_visibility_);
UpdateBackgroundThrottlingState(NotificationPolicy::kDoNotNotifyFrames);
UpdateBackgroundThrottlingState();
NotifyFrames();
}
void PageSchedulerImpl::SetPageFrozen(bool frozen) {
SetPageFrozenImpl(frozen, NotificationPolicy::kNotifyFrames);
}
void PageSchedulerImpl::SetPageFrozenImpl(
bool frozen,
PageSchedulerImpl::NotificationPolicy notification_policy) {
if (is_frozen_ == frozen)
return;
is_frozen_ = frozen;
for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_)
frame_scheduler->SetPageFrozen(frozen);
frame_scheduler->SetPageFrozenForTracing(frozen);
if (delegate_)
delegate_->SetPageFrozen(frozen);
if (notification_policy ==
PageSchedulerImpl::NotificationPolicy::kNotifyFrames)
NotifyFrames();
}
void PageSchedulerImpl::SetKeepActive(bool keep_active) {
if (keep_active_ == keep_active)
return;
keep_active_ = keep_active;
for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_)
frame_scheduler->SetKeepActive(keep_active);
frame_scheduler->SetPageKeepActiveForTracing(keep_active);
NotifyFrames();
}
bool PageSchedulerImpl::KeepActive() const {
return keep_active_;
}
bool PageSchedulerImpl::IsMainFrameLocal() const {
......@@ -189,7 +207,7 @@ std::unique_ptr<FrameSchedulerImpl> PageSchedulerImpl::CreateFrameSchedulerImpl(
MaybeInitializeBackgroundCPUTimeBudgetPool();
std::unique_ptr<FrameSchedulerImpl> frame_scheduler(new FrameSchedulerImpl(
main_thread_scheduler_, this, blame_context, frame_type));
frame_scheduler->SetPageVisibility(page_visibility_);
frame_scheduler->UpdatePolicy();
frame_schedulers_.insert(frame_scheduler.get());
return frame_scheduler;
}
......@@ -261,7 +279,8 @@ void PageSchedulerImpl::AudioStateChanged(bool is_audio_playing) {
if (is_audio_playing) {
audio_state_ = AudioState::kAudible;
on_audio_silent_closure_.Cancel();
UpdateFramePolicies();
NotifyFrames();
main_thread_scheduler_->OnAudioStateChanged();
} else {
if (audio_state_ != AudioState::kAudible)
return;
......@@ -270,16 +289,16 @@ void PageSchedulerImpl::AudioStateChanged(bool is_audio_playing) {
audio_state_ = AudioState::kRecentlyAudible;
main_thread_scheduler_->ControlTaskQueue()->PostDelayedTask(
FROM_HERE, on_audio_silent_closure_.GetCallback(), kRecentAudioDelay);
// No need to call UpdateFramePolicies here, as for outside world
// No need to call NotifyFrames or
// MainThreadScheduler::OnAudioStateChanged here, as for outside world
// kAudible and kRecentlyAudible are the same thing.
}
main_thread_scheduler_->OnAudioStateChanged();
}
void PageSchedulerImpl::OnAudioSilent() {
DCHECK_EQ(audio_state_, AudioState::kRecentlyAudible);
audio_state_ = AudioState::kSilent;
UpdateFramePolicies();
NotifyFrames();
main_thread_scheduler_->OnAudioStateChanged();
}
......@@ -380,8 +399,6 @@ void PageSchedulerImpl::MaybeInitializeBackgroundCPUTimeBudgetPool() {
background_time_budget_pool_->SetMaxThrottlingDelay(
lazy_now.Now(), settings.max_throttling_delay);
UpdateBackgroundThrottlingState();
background_time_budget_pool_->SetTimeBudgetRecoveryRate(
lazy_now.Now(), settings.budget_recovery_rate);
......@@ -389,6 +406,8 @@ void PageSchedulerImpl::MaybeInitializeBackgroundCPUTimeBudgetPool() {
background_time_budget_pool_->GrantAdditionalBudget(
lazy_now.Now(), settings.initial_budget.value());
}
UpdateBackgroundBudgetPoolThrottlingState();
}
void PageSchedulerImpl::OnThrottlingReported(
......@@ -411,27 +430,27 @@ void PageSchedulerImpl::OnThrottlingReported(
delegate_->ReportIntervention(String::FromUTF8(message.c_str()));
}
void PageSchedulerImpl::UpdateBackgroundThrottlingState() {
void PageSchedulerImpl::UpdateBackgroundThrottlingState(
NotificationPolicy notification_policy) {
if (page_visibility_ == PageVisibilityState::kVisible) {
is_throttled_ = false;
on_page_throttled_closure_.Cancel();
do_throttle_page_callback_.Cancel();
UpdateBackgroundBudgetPoolThrottlingState();
} else {
main_thread_scheduler_->ControlTaskQueue()->PostDelayedTask(
FROM_HERE, on_page_throttled_closure_.GetCallback(),
FROM_HERE, do_throttle_page_callback_.GetCallback(),
kThrottlingDelayAfterBackgrounding);
}
// Do not call UpdateFramePolicies here because it's already been triggered
// by FrameScheduler::SetPageVisible.
// TODO(altimin): Remove FrameScheduler::SetPageVisible and call
// UpdateFramePolicies here.
if (notification_policy == NotificationPolicy::kNotifyFrames)
NotifyFrames();
}
void PageSchedulerImpl::OnPageThrottled() {
on_page_throttled_closure_.Cancel();
void PageSchedulerImpl::DoThrottlePage() {
do_throttle_page_callback_.Cancel();
is_throttled_ = true;
UpdateFramePolicies();
UpdateBackgroundBudgetPoolThrottlingState();
NotifyFrames();
}
void PageSchedulerImpl::UpdateBackgroundBudgetPoolThrottlingState() {
......@@ -447,7 +466,7 @@ void PageSchedulerImpl::UpdateBackgroundBudgetPoolThrottlingState() {
}
}
void PageSchedulerImpl::UpdateFramePolicies() {
void PageSchedulerImpl::NotifyFrames() {
for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_)
frame_scheduler->UpdatePolicy();
}
......
......@@ -82,6 +82,7 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// Note that the frame can throttle queues even when the page is not throttled
// (e.g. for offscreen frames or recently backgrounded pages).
bool IsThrottled() const;
bool KeepActive() const;
std::unique_ptr<FrameSchedulerImpl> CreateFrameSchedulerImpl(
base::trace_event::BlameContext*,
......@@ -115,6 +116,12 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
kRecentlyAudible,
};
enum class NotificationPolicy { kNotifyFrames, kDoNotNotifyFrames };
// Support not issuing a notification to frames when we disable freezing as
// a part of foregrounding the page.
void SetPageFrozenImpl(bool frozen, NotificationPolicy notification_policy);
CPUTimeBudgetPool* BackgroundCPUTimeBudgetPool();
void MaybeInitializeBackgroundCPUTimeBudgetPool();
......@@ -122,7 +129,7 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// Depending on page visibility, either turns throttling off, or schedules a
// call to enable it after a grace period.
void UpdateBackgroundThrottlingState();
void UpdateBackgroundThrottlingState(NotificationPolicy notification_policy);
// As a part of UpdateBackgroundThrottlingState set correct
// background_time_budget_pool_ state depending on page visibility and
......@@ -136,9 +143,10 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// Callback for enabling throttling in background after specified delay.
// TODO(altimin): Trigger throttling depending on the loading state
// of the page.
void OnPageThrottled();
void DoThrottlePage();
void UpdateFramePolicies();
// Notify frames that the page scheduler state has been updated.
void NotifyFrames();
void EnableThrottling();
......@@ -155,9 +163,10 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
bool nested_runloop_;
bool is_main_frame_local_;
bool is_throttled_;
bool keep_active_;
CPUTimeBudgetPool* background_time_budget_pool_; // Not owned.
PageScheduler::Delegate* delegate_; // Not owned.
CancelableClosureHolder on_page_throttled_closure_;
CancelableClosureHolder do_throttle_page_callback_;
CancelableClosureHolder on_audio_silent_closure_;
base::WeakPtrFactory<PageSchedulerImpl> weak_factory_;
......
......@@ -82,21 +82,13 @@ class FrameScheduler : public FrameOrWorkerScheduler {
// Query the page visibility state for the page associated with this frame.
// The scheduler may throttle tasks associated with pages that are not
// visible.
// TODO(altimin): Remove this method.
virtual bool IsPageVisible() const = 0;
// Set whether this frame is suspended. Only unthrottledTaskRunner tasks are
// allowed to run on a suspended frame.
virtual void SetPaused(bool) = 0;
// Notifies observers of transitioning to and from FROZEN state in
// background.
virtual void SetPageFrozen(bool) {}
// Tells the scheduler about "keep-alive" state which can be due to:
// service workers, shared workers, or fetch keep-alive.
// If true, then the scheduler should not freeze relevant task queues.
virtual void SetKeepActive(bool) {}
// Set whether this frame is cross origin w.r.t. the top level frame. Cross
// origin frames may use a different scheduling policy from same origin
// frames.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment