Commit cde1b24d authored by Takashi Toyoshima's avatar Takashi Toyoshima Committed by Commit Bot

Loading Dispatcher: Implement WebFrameScheduler::Observer interface

This patch adds an Observer interface to WebFrameScheduler so that
platform/loader can implement Blink scheduler backed throttling scheme.

Observer will be notified when scheduler's throttling state is changed.
Internally, this means the page visibility is changed to which the frame
belongs.

BUG=729953

Change-Id: I851b153fef2e0c6ada748bee997bc1e69292e08d
Reviewed-on: https://chromium-review.googlesource.com/525198Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarSami Kyöstilä <skyostil@chromium.org>
Reviewed-by: default avatarKunihiko Sakamoto <ksakamoto@chromium.org>
Commit-Queue: Takashi Toyoshima <toyoshim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#481808}
parent e6357aab
...@@ -71,6 +71,8 @@ class EmptyPopupMenu : public PopupMenu { ...@@ -71,6 +71,8 @@ class EmptyPopupMenu : public PopupMenu {
class EmptyFrameScheduler : public WebFrameScheduler { class EmptyFrameScheduler : public WebFrameScheduler {
public: public:
EmptyFrameScheduler() { DCHECK(IsMainThread()); } EmptyFrameScheduler() { DCHECK(IsMainThread()); }
void AddThrottlingObserver(ObserverType, Observer*) override {}
void RemoveThrottlingObserver(ObserverType, Observer*) override {}
void SetFrameVisible(bool) override {} void SetFrameVisible(bool) override {}
RefPtr<WebTaskRunner> LoadingTaskRunner() override; RefPtr<WebTaskRunner> LoadingTaskRunner() override;
RefPtr<WebTaskRunner> TimerTaskRunner() override; RefPtr<WebTaskRunner> TimerTaskRunner() override;
......
...@@ -18,6 +18,15 @@ class WebFrameScheduler { ...@@ -18,6 +18,15 @@ class WebFrameScheduler {
public: public:
virtual ~WebFrameScheduler() {} virtual ~WebFrameScheduler() {}
// Observer type that regulates conditions to invoke callbacks.
enum class ObserverType { kLoader };
// Represents throttling state.
enum class ThrottlingState {
kThrottled,
kNotThrottled,
};
class ActiveConnectionHandle { class ActiveConnectionHandle {
public: public:
ActiveConnectionHandle() {} ActiveConnectionHandle() {}
...@@ -27,6 +36,21 @@ class WebFrameScheduler { ...@@ -27,6 +36,21 @@ class WebFrameScheduler {
DISALLOW_COPY_AND_ASSIGN(ActiveConnectionHandle); DISALLOW_COPY_AND_ASSIGN(ActiveConnectionHandle);
}; };
// Observer interface to receive scheduling policy change events.
class Observer {
public:
// Notified when throttling state is changed.
virtual void OnThrottlingStateChanged(ThrottlingState) = 0;
};
// Adds an Observer instance to be notified on scheduling policy changed.
// When an Observer is added, the initial state will be notified synchronously
// through the Observer interface.
virtual void AddThrottlingObserver(ObserverType, Observer*) = 0;
// Removes an Observer instance.
virtual void RemoveThrottlingObserver(ObserverType, Observer*) = 0;
// The scheduler may throttle tasks associated with offscreen frames. // The scheduler may throttle tasks associated with offscreen frames.
virtual void SetFrameVisible(bool) {} virtual void SetFrameVisible(bool) {}
......
...@@ -106,6 +106,25 @@ void WebFrameSchedulerImpl::RemoveTimerQueueFromBackgroundCPUTimeBudgetPool() { ...@@ -106,6 +106,25 @@ void WebFrameSchedulerImpl::RemoveTimerQueueFromBackgroundCPUTimeBudgetPool() {
timer_task_queue_.get()); timer_task_queue_.get());
} }
void WebFrameSchedulerImpl::AddThrottlingObserver(ObserverType type,
Observer* observer) {
DCHECK_EQ(ObserverType::kLoader, type);
DCHECK(observer);
observer->OnThrottlingStateChanged(page_visible_
? ThrottlingState::kNotThrottled
: ThrottlingState::kThrottled);
loader_observers_.insert(observer);
}
void WebFrameSchedulerImpl::RemoveThrottlingObserver(ObserverType type,
Observer* observer) {
DCHECK_EQ(ObserverType::kLoader, type);
DCHECK(observer);
const auto found = loader_observers_.find(observer);
DCHECK(loader_observers_.end() != found);
loader_observers_.erase(found);
}
void WebFrameSchedulerImpl::SetFrameVisible(bool frame_visible) { void WebFrameSchedulerImpl::SetFrameVisible(bool frame_visible) {
DCHECK(parent_web_view_scheduler_); DCHECK(parent_web_view_scheduler_);
if (frame_visible_ == frame_visible) if (frame_visible_ == frame_visible)
...@@ -301,6 +320,12 @@ void WebFrameSchedulerImpl::SetPageVisible(bool page_visible) { ...@@ -301,6 +320,12 @@ void WebFrameSchedulerImpl::SetPageVisible(bool page_visible) {
bool was_throttled = ShouldThrottleTimers(); bool was_throttled = ShouldThrottleTimers();
page_visible_ = page_visible; page_visible_ = page_visible;
UpdateTimerThrottling(was_throttled); UpdateTimerThrottling(was_throttled);
for (auto observer : loader_observers_) {
observer->OnThrottlingStateChanged(page_visible_
? ThrottlingState::kNotThrottled
: ThrottlingState::kThrottled);
}
} }
void WebFrameSchedulerImpl::SetSuspended(bool frame_suspended) { void WebFrameSchedulerImpl::SetSuspended(bool frame_suspended) {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_WEB_FRAME_SCHEDULER_IMPL_H_ #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_WEB_FRAME_SCHEDULER_IMPL_H_
#include <memory> #include <memory>
#include <set>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
...@@ -39,6 +40,8 @@ class WebFrameSchedulerImpl : public WebFrameScheduler { ...@@ -39,6 +40,8 @@ class WebFrameSchedulerImpl : public WebFrameScheduler {
~WebFrameSchedulerImpl() override; ~WebFrameSchedulerImpl() override;
// WebFrameScheduler implementation: // WebFrameScheduler implementation:
void AddThrottlingObserver(ObserverType, Observer*) override;
void RemoveThrottlingObserver(ObserverType, Observer*) override;
void SetFrameVisible(bool frame_visible) override; void SetFrameVisible(bool frame_visible) override;
void SetPageVisible(bool page_visible) override; void SetPageVisible(bool page_visible) override;
void SetSuspended(bool frame_suspended) override; void SetSuspended(bool frame_suspended) override;
...@@ -60,7 +63,6 @@ class WebFrameSchedulerImpl : public WebFrameScheduler { ...@@ -60,7 +63,6 @@ class WebFrameSchedulerImpl : public WebFrameScheduler {
void SetDocumentParsingInBackground(bool background_parser_active) override; void SetDocumentParsingInBackground(bool background_parser_active) override;
void OnFirstMeaningfulPaint() override; void OnFirstMeaningfulPaint() override;
std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override; std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override;
void AsValueInto(base::trace_event::TracedValue* state) const; void AsValueInto(base::trace_event::TracedValue* state) const;
bool has_active_connection() const { return active_connection_count_; } bool has_active_connection() const { return active_connection_count_; }
...@@ -107,6 +109,7 @@ class WebFrameSchedulerImpl : public WebFrameScheduler { ...@@ -107,6 +109,7 @@ class WebFrameSchedulerImpl : public WebFrameScheduler {
RendererSchedulerImpl* renderer_scheduler_; // NOT OWNED RendererSchedulerImpl* renderer_scheduler_; // NOT OWNED
WebViewSchedulerImpl* parent_web_view_scheduler_; // NOT OWNED WebViewSchedulerImpl* parent_web_view_scheduler_; // NOT OWNED
base::trace_event::BlameContext* blame_context_; // NOT OWNED base::trace_event::BlameContext* blame_context_; // NOT OWNED
std::set<Observer*> loader_observers_; // NOT OWNED
bool frame_visible_; bool frame_visible_;
bool page_visible_; bool page_visible_;
bool frame_suspended_; bool frame_suspended_;
......
...@@ -58,6 +58,35 @@ class WebFrameSchedulerImplTest : public testing::Test { ...@@ -58,6 +58,35 @@ class WebFrameSchedulerImplTest : public testing::Test {
namespace { namespace {
class MockThrottlingObserver : 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); void RunRepeatingTask(RefPtr<WebTaskRunner> task_runner, int* run_count);
std::unique_ptr<WTF::Closure> MakeRepeatingTask( std::unique_ptr<WTF::Closure> MakeRepeatingTask(
...@@ -209,5 +238,46 @@ TEST_F(WebFrameSchedulerImplTest, SuspendAndResume) { ...@@ -209,5 +238,46 @@ TEST_F(WebFrameSchedulerImplTest, SuspendAndResume) {
EXPECT_EQ(5, counter); 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 scheduler
} // namespace blink } // namespace blink
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