| Index: components/scheduler/renderer/web_view_scheduler_impl.cc
|
| diff --git a/components/scheduler/renderer/web_view_scheduler_impl.cc b/components/scheduler/renderer/web_view_scheduler_impl.cc
|
| index da4e80b30b6fdcd2655f330e39d74d0bfb386137..0e41a26bbf4bdaabd7fa0062a055cd9d7a4c3b00 100644
|
| --- a/components/scheduler/renderer/web_view_scheduler_impl.cc
|
| +++ b/components/scheduler/renderer/web_view_scheduler_impl.cc
|
| @@ -5,6 +5,7 @@
|
| #include "components/scheduler/renderer/web_view_scheduler_impl.h"
|
|
|
| #include "base/logging.h"
|
| +#include "components/scheduler/base/real_time_domain.h"
|
| #include "components/scheduler/base/virtual_time_domain.h"
|
| #include "components/scheduler/child/scheduler_tqm_delegate.h"
|
| #include "components/scheduler/renderer/auto_advancing_virtual_time_domain.h"
|
| @@ -27,7 +28,8 @@ WebViewSchedulerImpl::WebViewSchedulerImpl(
|
| virtual_time_policy_(VirtualTimePolicy::ADVANCE),
|
| page_visible_(true),
|
| disable_background_timer_throttling_(disable_background_timer_throttling),
|
| - allow_virtual_time_to_advance_(true) {
|
| + allow_virtual_time_to_advance_(true),
|
| + have_seen_loading_task_(false) {
|
| renderer_scheduler->AddWebViewScheduler(this);
|
| }
|
|
|
| @@ -38,8 +40,14 @@ WebViewSchedulerImpl::~WebViewSchedulerImpl() {
|
| frame_scheduler->DetachFromWebViewScheduler();
|
| }
|
| renderer_scheduler_->RemoveWebViewScheduler(this);
|
| - if (virtual_time_domain_)
|
| + if (virtual_time_domain_) {
|
| + // Since we're just about to delete virtual_time_domain_ we'd better move
|
| + // the per-thread task queues back to the RealTimeDomain or we risk a UAF
|
| + // when the task queues get deleted.
|
| + renderer_scheduler_->SetPerThreadTaskRunnerTimeDomain(
|
| + renderer_scheduler_->real_time_domain());
|
| renderer_scheduler_->UnregisterTimeDomain(virtual_time_domain_.get());
|
| + }
|
| }
|
|
|
| void WebViewSchedulerImpl::setPageVisible(bool page_visible) {
|
| @@ -98,6 +106,10 @@ void WebViewSchedulerImpl::enableVirtualTime() {
|
| for (WebFrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
|
| frame_scheduler->OnVirtualTimeDomainChanged();
|
| }
|
| +
|
| + // For determinism the per-thread task queues must use virtual time too.
|
| + renderer_scheduler_->SetPerThreadTaskRunnerTimeDomain(
|
| + virtual_time_domain_.get());
|
| }
|
|
|
| void WebViewSchedulerImpl::setAllowVirtualTimeToAdvance(
|
| @@ -119,6 +131,7 @@ bool WebViewSchedulerImpl::virtualTimeAllowedToAdvance() const {
|
|
|
| void WebViewSchedulerImpl::DidStartLoading(unsigned long identifier) {
|
| pending_loads_.insert(identifier);
|
| + have_seen_loading_task_ = true;
|
|
|
| if (virtual_time_policy_ !=
|
| VirtualTimePolicy::PAUSE_IF_NETWORK_FETCHES_PENDING) {
|
| @@ -154,7 +167,11 @@ void WebViewSchedulerImpl::setVirtualTimePolicy(VirtualTimePolicy policy) {
|
| break;
|
|
|
| case VirtualTimePolicy::PAUSE_IF_NETWORK_FETCHES_PENDING:
|
| - setAllowVirtualTimeToAdvance(pending_loads_.size() == 0);
|
| + // We pause virtual time until we've seen a loading task posted, because
|
| + // otherwise we could advance virtual time arbitarially far before the
|
| + // first load arrives.
|
| + setAllowVirtualTimeToAdvance(pending_loads_.size() == 0 &&
|
| + have_seen_loading_task_);
|
| break;
|
| }
|
| }
|
|
|