// Copyright 2014 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 "components/scheduler/renderer/renderer_scheduler_impl.h"

#include "base/bind.h"
#include "base/debug/stack_trace.h"
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
#include "cc/output/begin_frame_args.h"
#include "components/scheduler/base/task_queue_impl.h"
#include "components/scheduler/base/task_queue_selector.h"
#include "components/scheduler/base/virtual_time_domain.h"
#include "components/scheduler/child/scheduler_tqm_delegate.h"
#include "components/scheduler/renderer/web_view_scheduler_impl.h"
#include "components/scheduler/renderer/webthread_impl_for_renderer_scheduler.h"

namespace scheduler {
namespace {
// The run time of loading tasks is strongly bimodal.  The vast majority are
// very cheap, but there are usually a handful of very expensive tasks (e.g ~1
// second on a mobile device) so we take a very pesimistic view when estimating
// the cost of loading tasks.
const int kLoadingTaskEstimationSampleCount = 1000;
const double kLoadingTaskEstimationPercentile = 99;
const int kTimerTaskEstimationSampleCount = 1000;
const double kTimerTaskEstimationPercentile = 99;
const int kShortIdlePeriodDurationSampleCount = 10;
const double kShortIdlePeriodDurationPercentile = 50;
}

RendererSchedulerImpl::RendererSchedulerImpl(
    scoped_refptr<SchedulerTqmDelegate> main_task_runner)
    : helper_(main_task_runner,
              "renderer.scheduler",
              TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
              TRACE_DISABLED_BY_DEFAULT("renderer.scheduler.debug")),
      idle_helper_(&helper_,
                   this,
                   "renderer.scheduler",
                   TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
                   "RendererSchedulerIdlePeriod",
                   base::TimeDelta()),
      render_widget_scheduler_signals_(this),
      control_task_runner_(helper_.ControlTaskRunner()),
      compositor_task_runner_(
          helper_.NewTaskQueue(TaskQueue::Spec("compositor_tq")
                                   .SetShouldMonitorQuiescence(true))),
      delayed_update_policy_runner_(
          base::Bind(&RendererSchedulerImpl::UpdatePolicy,
                     base::Unretained(this)),
          helper_.ControlTaskRunner()),
      main_thread_only_(compositor_task_runner_,
                        helper_.scheduler_tqm_delegate().get()),
      policy_may_need_update_(&any_thread_lock_),
      weak_factory_(this) {
  throttling_helper_.reset(new ThrottlingHelper(this, "renderer.scheduler"));
  update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy,
                                      weak_factory_.GetWeakPtr());
  end_renderer_hidden_idle_period_closure_.Reset(base::Bind(
      &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr()));

  suspend_timers_when_backgrounded_closure_.Reset(
      base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded,
                 weak_factory_.GetWeakPtr()));

  default_loading_task_runner_ = NewLoadingTaskRunner("default_loading_tq");
  default_timer_task_runner_ = NewTimerTaskRunner("default_timer_tq");

  TRACE_EVENT_OBJECT_CREATED_WITH_ID(
      TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
      this);

  helper_.SetObserver(this);
}

RendererSchedulerImpl::~RendererSchedulerImpl() {
  TRACE_EVENT_OBJECT_DELETED_WITH_ID(
      TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
      this);

  for (const scoped_refptr<TaskQueue>& loading_queue : loading_task_runners_) {
    loading_queue->RemoveTaskObserver(
        &MainThreadOnly().loading_task_cost_estimator);
  }
  for (const scoped_refptr<TaskQueue>& timer_queue : timer_task_runners_) {
    timer_queue->RemoveTaskObserver(
        &MainThreadOnly().timer_task_cost_estimator);
  }

  // Ensure the renderer scheduler was shut down explicitly, because otherwise
  // we could end up having stale pointers to the Blink heap which has been
  // terminated by this point.
  DCHECK(MainThreadOnly().was_shutdown);
}

RendererSchedulerImpl::MainThreadOnly::MainThreadOnly(
    const scoped_refptr<TaskQueue>& compositor_task_runner,
    base::TickClock* time_source)
    : loading_task_cost_estimator(time_source,
                                  kLoadingTaskEstimationSampleCount,
                                  kLoadingTaskEstimationPercentile),
      timer_task_cost_estimator(time_source,
                                kTimerTaskEstimationSampleCount,
                                kTimerTaskEstimationPercentile),
      idle_time_estimator(compositor_task_runner,
                          time_source,
                          kShortIdlePeriodDurationSampleCount,
                          kShortIdlePeriodDurationPercentile),
      current_use_case(UseCase::NONE),
      timer_queue_suspend_count(0),
      navigation_task_expected_count(0),
      renderer_hidden(false),
      renderer_backgrounded(false),
      timer_queue_suspension_when_backgrounded_enabled(false),
      timer_queue_suspended_when_backgrounded(false),
      was_shutdown(false),
      loading_tasks_seem_expensive(false),
      timer_tasks_seem_expensive(false),
      touchstart_expected_soon(false),
      have_seen_a_begin_main_frame(false),
      have_reported_blocking_intervention_in_current_policy(false),
      have_reported_blocking_intervention_since_navigation(false),
      has_visible_render_widget_with_touch_handler(false),
      begin_frame_not_expected_soon(false),
      expensive_task_blocking_allowed(true) {}

RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {}

RendererSchedulerImpl::AnyThread::AnyThread()
    : awaiting_touch_start_response(false),
      in_idle_period(false),
      begin_main_frame_on_critical_path(false),
      last_gesture_was_compositor_driven(false),
      have_seen_touchstart(false) {}

RendererSchedulerImpl::AnyThread::~AnyThread() {}

RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly()
    : last_input_type(blink::WebInputEvent::Undefined) {}

RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {}

void RendererSchedulerImpl::Shutdown() {
  throttling_helper_.reset();
  helper_.Shutdown();
  MainThreadOnly().was_shutdown = true;
}

scoped_ptr<blink::WebThread> RendererSchedulerImpl::CreateMainThread() {
  return make_scoped_ptr(new WebThreadImplForRendererScheduler(this));
}

scoped_refptr<TaskQueue> RendererSchedulerImpl::DefaultTaskRunner() {
  return helper_.DefaultTaskRunner();
}

scoped_refptr<TaskQueue> RendererSchedulerImpl::CompositorTaskRunner() {
  helper_.CheckOnValidThread();
  return compositor_task_runner_;
}

scoped_refptr<SingleThreadIdleTaskRunner>
RendererSchedulerImpl::IdleTaskRunner() {
  return idle_helper_.IdleTaskRunner();
}

scoped_refptr<TaskQueue> RendererSchedulerImpl::LoadingTaskRunner() {
  helper_.CheckOnValidThread();
  return default_loading_task_runner_;
}

scoped_refptr<TaskQueue> RendererSchedulerImpl::TimerTaskRunner() {
  helper_.CheckOnValidThread();
  return default_timer_task_runner_;
}

scoped_refptr<TaskQueue> RendererSchedulerImpl::ControlTaskRunner() {
  helper_.CheckOnValidThread();
  return helper_.ControlTaskRunner();
}

scoped_refptr<TaskQueue> RendererSchedulerImpl::NewLoadingTaskRunner(
    const char* name) {
  helper_.CheckOnValidThread();
  scoped_refptr<TaskQueue> loading_task_queue(helper_.NewTaskQueue(
      TaskQueue::Spec(name).SetShouldMonitorQuiescence(true)));
  loading_task_runners_.insert(loading_task_queue);
  loading_task_queue->SetQueueEnabled(
      MainThreadOnly().current_policy.loading_queue_policy.is_enabled);
  loading_task_queue->SetQueuePriority(
      MainThreadOnly().current_policy.loading_queue_policy.priority);
  loading_task_queue->AddTaskObserver(
      &MainThreadOnly().loading_task_cost_estimator);
  return loading_task_queue;
}

scoped_refptr<TaskQueue> RendererSchedulerImpl::NewTimerTaskRunner(
    const char* name) {
  helper_.CheckOnValidThread();
  scoped_refptr<TaskQueue> timer_task_queue(
      helper_.NewTaskQueue(TaskQueue::Spec(name)
                               .SetShouldMonitorQuiescence(true)
                               .SetShouldReportWhenExecutionBlocked(true)));
  timer_task_runners_.insert(timer_task_queue);
  timer_task_queue->SetQueueEnabled(
      MainThreadOnly().current_policy.timer_queue_policy.is_enabled);
  timer_task_queue->SetQueuePriority(
      MainThreadOnly().current_policy.timer_queue_policy.priority);
  timer_task_queue->AddTaskObserver(
      &MainThreadOnly().timer_task_cost_estimator);
  return timer_task_queue;
}

scoped_ptr<RenderWidgetSchedulingState>
RendererSchedulerImpl::NewRenderWidgetSchedulingState() {
  return render_widget_scheduler_signals_.NewRenderWidgetSchedulingState();
}

void RendererSchedulerImpl::OnUnregisterTaskQueue(
    const scoped_refptr<TaskQueue>& task_queue) {
  if (throttling_helper_.get())
    throttling_helper_->UnregisterTaskQueue(task_queue.get());

  if (loading_task_runners_.find(task_queue) != loading_task_runners_.end()) {
    task_queue->RemoveTaskObserver(
        &MainThreadOnly().loading_task_cost_estimator);
    loading_task_runners_.erase(task_queue);
  } else if (timer_task_runners_.find(task_queue) !=
             timer_task_runners_.end()) {
    task_queue->RemoveTaskObserver(&MainThreadOnly().timer_task_cost_estimator);
    timer_task_runners_.erase(task_queue);
  }
}

bool RendererSchedulerImpl::CanExceedIdleDeadlineIfRequired() const {
  return idle_helper_.CanExceedIdleDeadlineIfRequired();
}

void RendererSchedulerImpl::AddTaskObserver(
    base::MessageLoop::TaskObserver* task_observer) {
  helper_.AddTaskObserver(task_observer);
}

void RendererSchedulerImpl::RemoveTaskObserver(
    base::MessageLoop::TaskObserver* task_observer) {
  helper_.RemoveTaskObserver(task_observer);
}

void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) {
  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::WillBeginFrame", "args", args.AsValue());
  helper_.CheckOnValidThread();
  if (helper_.IsShutdown())
    return;

  EndIdlePeriod();
  MainThreadOnly().estimated_next_frame_begin = args.frame_time + args.interval;
  MainThreadOnly().have_seen_a_begin_main_frame = true;
  MainThreadOnly().begin_frame_not_expected_soon = false;
  MainThreadOnly().compositor_frame_interval = args.interval;
  {
    base::AutoLock lock(any_thread_lock_);
    AnyThread().begin_main_frame_on_critical_path = args.on_critical_path;
  }
}

void RendererSchedulerImpl::DidCommitFrameToCompositor() {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::DidCommitFrameToCompositor");
  helper_.CheckOnValidThread();
  if (helper_.IsShutdown())
    return;

  base::TimeTicks now(helper_.scheduler_tqm_delegate()->NowTicks());
  if (now < MainThreadOnly().estimated_next_frame_begin) {
    // TODO(rmcilroy): Consider reducing the idle period based on the runtime of
    // the next pending delayed tasks (as currently done in for long idle times)
    idle_helper_.StartIdlePeriod(
        IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, now,
        MainThreadOnly().estimated_next_frame_begin);
  }

  MainThreadOnly().idle_time_estimator.DidCommitFrameToCompositor();
}

void RendererSchedulerImpl::BeginFrameNotExpectedSoon() {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::BeginFrameNotExpectedSoon");
  helper_.CheckOnValidThread();
  if (helper_.IsShutdown())
    return;

  MainThreadOnly().begin_frame_not_expected_soon = true;
  idle_helper_.EnableLongIdlePeriod();
  {
    base::AutoLock lock(any_thread_lock_);
    AnyThread().begin_main_frame_on_critical_path = false;
  }
}

void RendererSchedulerImpl::SetAllRenderWidgetsHidden(bool hidden) {
  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::SetAllRenderWidgetsHidden", "hidden",
               hidden);

  helper_.CheckOnValidThread();

  if (helper_.IsShutdown() || MainThreadOnly().renderer_hidden == hidden)
    return;

  end_renderer_hidden_idle_period_closure_.Cancel();

  if (hidden) {
    idle_helper_.EnableLongIdlePeriod();

    // Ensure that we stop running idle tasks after a few seconds of being
    // hidden.
    base::TimeDelta end_idle_when_hidden_delay =
        base::TimeDelta::FromMilliseconds(kEndIdleWhenHiddenDelayMillis);
    control_task_runner_->PostDelayedTask(
        FROM_HERE, end_renderer_hidden_idle_period_closure_.callback(),
        end_idle_when_hidden_delay);
    MainThreadOnly().renderer_hidden = true;
  } else {
    MainThreadOnly().renderer_hidden = false;
    EndIdlePeriod();
  }

  // TODO(alexclarke): Should we update policy here?
  TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
      TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
      this, AsValue(helper_.scheduler_tqm_delegate()->NowTicks()));
}

void RendererSchedulerImpl::SetHasVisibleRenderWidgetWithTouchHandler(
    bool has_visible_render_widget_with_touch_handler) {
  helper_.CheckOnValidThread();
  if (has_visible_render_widget_with_touch_handler ==
      MainThreadOnly().has_visible_render_widget_with_touch_handler)
    return;

  MainThreadOnly().has_visible_render_widget_with_touch_handler =
      has_visible_render_widget_with_touch_handler;

  base::AutoLock lock(any_thread_lock_);
  UpdatePolicyLocked(UpdateType::FORCE_UPDATE);
}

void RendererSchedulerImpl::OnRendererBackgrounded() {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::OnRendererBackgrounded");
  helper_.CheckOnValidThread();
  if (helper_.IsShutdown() || MainThreadOnly().renderer_backgrounded)
    return;

  MainThreadOnly().renderer_backgrounded = true;
  if (!MainThreadOnly().timer_queue_suspension_when_backgrounded_enabled)
    return;

  suspend_timers_when_backgrounded_closure_.Cancel();
  base::TimeDelta suspend_timers_when_backgrounded_delay =
      base::TimeDelta::FromMilliseconds(
          kSuspendTimersWhenBackgroundedDelayMillis);
  control_task_runner_->PostDelayedTask(
      FROM_HERE, suspend_timers_when_backgrounded_closure_.callback(),
      suspend_timers_when_backgrounded_delay);
}

void RendererSchedulerImpl::OnRendererForegrounded() {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::OnRendererForegrounded");
  helper_.CheckOnValidThread();
  if (helper_.IsShutdown() || !MainThreadOnly().renderer_backgrounded)
    return;

  MainThreadOnly().renderer_backgrounded = false;
  suspend_timers_when_backgrounded_closure_.Cancel();
  ResumeTimerQueueWhenForegrounded();
}

void RendererSchedulerImpl::EndIdlePeriod() {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::EndIdlePeriod");
  helper_.CheckOnValidThread();
  idle_helper_.EndIdlePeriod();
}

// static
bool RendererSchedulerImpl::ShouldPrioritizeInputEvent(
    const blink::WebInputEvent& web_input_event) {
  // We regard MouseMove events with the left mouse button down as a signal
  // that the user is doing something requiring a smooth frame rate.
  if (web_input_event.type == blink::WebInputEvent::MouseMove &&
      (web_input_event.modifiers & blink::WebInputEvent::LeftButtonDown)) {
    return true;
  }
  // Ignore all other mouse events because they probably don't signal user
  // interaction needing a smooth framerate. NOTE isMouseEventType returns false
  // for mouse wheel events, hence we regard them as user input.
  // Ignore keyboard events because it doesn't really make sense to enter
  // compositor priority for them.
  if (blink::WebInputEvent::isMouseEventType(web_input_event.type) ||
      blink::WebInputEvent::isKeyboardEventType(web_input_event.type)) {
    return false;
  }
  return true;
}

void RendererSchedulerImpl::DidHandleInputEventOnCompositorThread(
    const blink::WebInputEvent& web_input_event,
    InputEventState event_state) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::DidHandleInputEventOnCompositorThread");
  if (!ShouldPrioritizeInputEvent(web_input_event))
    return;

  UpdateForInputEventOnCompositorThread(web_input_event.type, event_state);
}

void RendererSchedulerImpl::DidAnimateForInputOnCompositorThread() {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::DidAnimateForInputOnCompositorThread");
  base::AutoLock lock(any_thread_lock_);
  AnyThread().fling_compositor_escalation_deadline =
      helper_.scheduler_tqm_delegate()->NowTicks() +
      base::TimeDelta::FromMilliseconds(kFlingEscalationLimitMillis);
}

void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread(
    blink::WebInputEvent::Type type,
    InputEventState input_event_state) {
  base::AutoLock lock(any_thread_lock_);
  base::TimeTicks now = helper_.scheduler_tqm_delegate()->NowTicks();

  // TODO(alexclarke): Move WebInputEventTraits where we can access it from here
  // and record the name rather than the integer representation.
  TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::UpdateForInputEventOnCompositorThread",
               "type", static_cast<int>(type), "input_event_state",
               InputEventStateToString(input_event_state));

  bool gesture_already_in_progress = InputSignalsSuggestGestureInProgress(now);
  bool was_awaiting_touch_start_response =
      AnyThread().awaiting_touch_start_response;

  AnyThread().user_model.DidStartProcessingInputEvent(type, now);

  if (input_event_state == InputEventState::EVENT_CONSUMED_BY_COMPOSITOR)
    AnyThread().user_model.DidFinishProcessingInputEvent(now);

  if (type) {
    switch (type) {
      case blink::WebInputEvent::TouchStart:
        AnyThread().awaiting_touch_start_response = true;
        // This is just a fail-safe to reset the state of
        // |last_gesture_was_compositor_driven| to the default. We don't know
        // yet where the gesture will run.
        AnyThread().last_gesture_was_compositor_driven = false;
        AnyThread().have_seen_touchstart = true;
        break;

      case blink::WebInputEvent::TouchMove:
        // Observation of consecutive touchmoves is a strong signal that the
        // page is consuming the touch sequence, in which case touchstart
        // response prioritization is no longer necessary. Otherwise, the
        // initial touchmove should preserve the touchstart response pending
        // state.
        if (AnyThread().awaiting_touch_start_response &&
            CompositorThreadOnly().last_input_type ==
                blink::WebInputEvent::TouchMove) {
          AnyThread().awaiting_touch_start_response = false;
        }
        break;

      case blink::WebInputEvent::GesturePinchUpdate:
      case blink::WebInputEvent::GestureScrollUpdate:
        AnyThread().last_gesture_was_compositor_driven =
            input_event_state == InputEventState::EVENT_CONSUMED_BY_COMPOSITOR;
        AnyThread().awaiting_touch_start_response = false;
        break;

      case blink::WebInputEvent::GestureFlingCancel:
        AnyThread().fling_compositor_escalation_deadline = base::TimeTicks();
        break;

      case blink::WebInputEvent::GestureTapDown:
      case blink::WebInputEvent::GestureShowPress:
      case blink::WebInputEvent::GestureScrollEnd:
        // With no observable effect, these meta events do not indicate a
        // meaningful touchstart response and should not impact task priority.
        break;

      default:
        AnyThread().awaiting_touch_start_response = false;
        break;
    }
  }

  // Avoid unnecessary policy updates, while a gesture is already in progress.
  if (!gesture_already_in_progress ||
      was_awaiting_touch_start_response !=
          AnyThread().awaiting_touch_start_response) {
    EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE);
  }
  CompositorThreadOnly().last_input_type = type;
}

void RendererSchedulerImpl::DidHandleInputEventOnMainThread(
    const blink::WebInputEvent& web_input_event) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::DidHandleInputEventOnMainThread");
  helper_.CheckOnValidThread();
  if (ShouldPrioritizeInputEvent(web_input_event)) {
    base::AutoLock lock(any_thread_lock_);
    AnyThread().user_model.DidFinishProcessingInputEvent(
        helper_.scheduler_tqm_delegate()->NowTicks());
  }
}

bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() {
  helper_.CheckOnValidThread();
  if (helper_.IsShutdown())
    return false;

  MaybeUpdatePolicy();
  // The touchstart, synchronized gesture and main-thread gesture use cases
  // indicate a strong likelihood of high-priority work in the near future.
  UseCase use_case = MainThreadOnly().current_use_case;
  return MainThreadOnly().touchstart_expected_soon ||
         use_case == UseCase::TOUCHSTART ||
         use_case == UseCase::MAIN_THREAD_GESTURE ||
         use_case == UseCase::SYNCHRONIZED_GESTURE;
}

bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() {
  helper_.CheckOnValidThread();
  if (helper_.IsShutdown())
    return false;

  MaybeUpdatePolicy();
  // We only yield if there's a urgent task to be run now, or we are expecting
  // one soon (touch start).
  // Note: even though the control queue has the highest priority we don't yield
  // for it since these tasks are not user-provided work and they are only
  // intended to run before the next task, not interrupt the tasks.
  switch (MainThreadOnly().current_use_case) {
    case UseCase::COMPOSITOR_GESTURE:
    case UseCase::NONE:
      return MainThreadOnly().touchstart_expected_soon;

    case UseCase::MAIN_THREAD_GESTURE:
    case UseCase::SYNCHRONIZED_GESTURE:
      return compositor_task_runner_->HasPendingImmediateWork() ||
             MainThreadOnly().touchstart_expected_soon;

    case UseCase::TOUCHSTART:
      return true;

    case UseCase::LOADING:
      return false;

    default:
      NOTREACHED();
      return false;
  }
}

base::TimeTicks RendererSchedulerImpl::CurrentIdleTaskDeadlineForTesting()
    const {
  return idle_helper_.CurrentIdleTaskDeadline();
}

void RendererSchedulerImpl::MaybeUpdatePolicy() {
  helper_.CheckOnValidThread();
  if (policy_may_need_update_.IsSet()) {
    UpdatePolicy();
  }
}

void RendererSchedulerImpl::EnsureUrgentPolicyUpdatePostedOnMainThread(
    const tracked_objects::Location& from_here) {
  // TODO(scheduler-dev): Check that this method isn't called from the main
  // thread.
  any_thread_lock_.AssertAcquired();
  if (!policy_may_need_update_.IsSet()) {
    policy_may_need_update_.SetWhileLocked(true);
    control_task_runner_->PostTask(from_here, update_policy_closure_);
  }
}

void RendererSchedulerImpl::UpdatePolicy() {
  base::AutoLock lock(any_thread_lock_);
  UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED);
}

void RendererSchedulerImpl::ForceUpdatePolicy() {
  base::AutoLock lock(any_thread_lock_);
  UpdatePolicyLocked(UpdateType::FORCE_UPDATE);
}

void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
  helper_.CheckOnValidThread();
  any_thread_lock_.AssertAcquired();
  if (helper_.IsShutdown())
    return;

  base::TimeTicks now = helper_.scheduler_tqm_delegate()->NowTicks();
  policy_may_need_update_.SetWhileLocked(false);

  base::TimeDelta expected_use_case_duration;
  UseCase use_case = ComputeCurrentUseCase(now, &expected_use_case_duration);
  MainThreadOnly().current_use_case = use_case;

  base::TimeDelta touchstart_expected_flag_valid_for_duration;
  bool touchstart_expected_soon = false;
  if (MainThreadOnly().has_visible_render_widget_with_touch_handler) {
    touchstart_expected_soon = AnyThread().user_model.IsGestureExpectedSoon(
        now, &touchstart_expected_flag_valid_for_duration);
  }
  MainThreadOnly().touchstart_expected_soon = touchstart_expected_soon;

  base::TimeDelta longest_jank_free_task_duration =
      EstimateLongestJankFreeTaskDuration();
  MainThreadOnly().longest_jank_free_task_duration =
      longest_jank_free_task_duration;

  bool loading_tasks_seem_expensive = false;
  bool timer_tasks_seem_expensive = false;
  loading_tasks_seem_expensive =
      MainThreadOnly().loading_task_cost_estimator.expected_task_duration() >
      longest_jank_free_task_duration;
  timer_tasks_seem_expensive =
      MainThreadOnly().timer_task_cost_estimator.expected_task_duration() >
      longest_jank_free_task_duration;
  MainThreadOnly().timer_tasks_seem_expensive = timer_tasks_seem_expensive;
  MainThreadOnly().loading_tasks_seem_expensive = loading_tasks_seem_expensive;

  // The |new_policy_duration| is the minimum of |expected_use_case_duration|
  // and |touchstart_expected_flag_valid_for_duration| unless one is zero in
  // which case we choose the other.
  base::TimeDelta new_policy_duration = expected_use_case_duration;
  if (new_policy_duration == base::TimeDelta() ||
      (touchstart_expected_flag_valid_for_duration > base::TimeDelta() &&
       new_policy_duration > touchstart_expected_flag_valid_for_duration)) {
    new_policy_duration = touchstart_expected_flag_valid_for_duration;
  }

  if (new_policy_duration > base::TimeDelta()) {
    MainThreadOnly().current_policy_expiration_time = now + new_policy_duration;
    delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration,
                                              now);
  } else {
    MainThreadOnly().current_policy_expiration_time = base::TimeTicks();
  }

  Policy new_policy;
  enum class ExpensiveTaskPolicy { RUN, BLOCK, THROTTLE };
  ExpensiveTaskPolicy expensive_task_policy = ExpensiveTaskPolicy::RUN;
  switch (use_case) {
    case UseCase::COMPOSITOR_GESTURE:
      if (touchstart_expected_soon) {
        expensive_task_policy = ExpensiveTaskPolicy::BLOCK;
        new_policy.compositor_queue_policy.priority = TaskQueue::HIGH_PRIORITY;
      } else {
        // What we really want to do is priorize loading tasks, but that doesn't
        // seem to be safe. Instead we do that by proxy by deprioritizing
        // compositor tasks. This should be safe since we've already gone to the
        // pain of fixing ordering issues with them.
        new_policy.compositor_queue_policy.priority =
            TaskQueue::BEST_EFFORT_PRIORITY;
      }
      break;

    case UseCase::SYNCHRONIZED_GESTURE:
      new_policy.compositor_queue_policy.priority = TaskQueue::HIGH_PRIORITY;
      if (touchstart_expected_soon) {
        expensive_task_policy = ExpensiveTaskPolicy::BLOCK;
      } else {
        expensive_task_policy = ExpensiveTaskPolicy::THROTTLE;
      }
      break;

    case UseCase::MAIN_THREAD_GESTURE:
      // In main thread gestures we don't have perfect knowledge about which
      // things we should be prioritizing, so we don't attempt to block
      // expensive tasks because we don't know whether they were integral to the
      // page's functionality or not.
      new_policy.compositor_queue_policy.priority = TaskQueue::HIGH_PRIORITY;
      break;

    case UseCase::TOUCHSTART:
      new_policy.compositor_queue_policy.priority = TaskQueue::HIGH_PRIORITY;
      new_policy.loading_queue_policy.is_enabled = false;
      new_policy.timer_queue_policy.is_enabled = false;
      // NOTE this is a nop due to the above.
      expensive_task_policy = ExpensiveTaskPolicy::BLOCK;
      break;

    case UseCase::NONE:
      // It's only safe to block tasks that if we are expecting a compositor
      // driven gesture.
      if (touchstart_expected_soon &&
          AnyThread().last_gesture_was_compositor_driven) {
        expensive_task_policy = ExpensiveTaskPolicy::BLOCK;
      }
      break;

    case UseCase::LOADING:
      new_policy.loading_queue_policy.priority = TaskQueue::HIGH_PRIORITY;
      new_policy.default_queue_policy.priority = TaskQueue::HIGH_PRIORITY;
      break;

    default:
      NOTREACHED();
  }

  if (expensive_task_policy == ExpensiveTaskPolicy::BLOCK &&
      (!MainThreadOnly().expensive_task_blocking_allowed ||
       !MainThreadOnly().have_seen_a_begin_main_frame ||
       MainThreadOnly().navigation_task_expected_count > 0)) {
    expensive_task_policy = ExpensiveTaskPolicy::RUN;
  }

  switch (expensive_task_policy) {
    case ExpensiveTaskPolicy::RUN:
      break;

    case ExpensiveTaskPolicy::BLOCK:
      if (loading_tasks_seem_expensive)
        new_policy.loading_queue_policy.is_enabled = false;
      if (timer_tasks_seem_expensive)
        new_policy.timer_queue_policy.is_enabled = false;
      break;

    case ExpensiveTaskPolicy::THROTTLE:
      if (loading_tasks_seem_expensive) {
        new_policy.loading_queue_policy.time_domain_type =
            TimeDomainType::THROTTLED;
      }
      if (timer_tasks_seem_expensive) {
        new_policy.timer_queue_policy.time_domain_type =
            TimeDomainType::THROTTLED;
      }
      break;
  }

  if (MainThreadOnly().timer_queue_suspend_count != 0 ||
      MainThreadOnly().timer_queue_suspended_when_backgrounded) {
    new_policy.timer_queue_policy.is_enabled = false;
  }

  // Tracing is done before the early out check, because it's quite possible we
  // will otherwise miss this information in traces.
  TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
      TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
      this, AsValueLocked(now));
  TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case",
                 use_case);
  TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
                 "RendererScheduler.loading_tasks_seem_expensive",
                 MainThreadOnly().loading_tasks_seem_expensive);
  TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
                 "RendererScheduler.timer_tasks_seem_expensive",
                 MainThreadOnly().timer_tasks_seem_expensive);

  // TODO(alexclarke): Can we get rid of force update now?
  if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED &&
      new_policy == MainThreadOnly().current_policy) {
    return;
  }

  ApplyTaskQueuePolicy(compositor_task_runner_.get(),
                       MainThreadOnly().current_policy.compositor_queue_policy,
                       new_policy.compositor_queue_policy);

  for (const scoped_refptr<TaskQueue>& loading_queue : loading_task_runners_) {
    ApplyTaskQueuePolicy(loading_queue.get(),
                         MainThreadOnly().current_policy.loading_queue_policy,
                         new_policy.loading_queue_policy);
  }

  for (const scoped_refptr<TaskQueue>& timer_queue : timer_task_runners_) {
    ApplyTaskQueuePolicy(timer_queue.get(),
                         MainThreadOnly().current_policy.timer_queue_policy,
                         new_policy.timer_queue_policy);
  }
  MainThreadOnly().have_reported_blocking_intervention_in_current_policy =
      false;

  // TODO(alexclarke): We shouldn't have to prioritize the default queue, but it
  // appears to be necessary since the order of loading tasks and IPCs (which
  // are mostly dispatched on the default queue) need to be preserved.
  ApplyTaskQueuePolicy(helper_.DefaultTaskRunner().get(),
                       MainThreadOnly().current_policy.default_queue_policy,
                       new_policy.default_queue_policy);

  DCHECK(compositor_task_runner_->IsQueueEnabled());
  MainThreadOnly().current_policy = new_policy;
}

void RendererSchedulerImpl::ApplyTaskQueuePolicy(
    TaskQueue* task_queue,
    const TaskQueuePolicy& old_task_queue_policy,
    const TaskQueuePolicy& new_task_queue_policy) const {
  task_queue->SetQueueEnabled(new_task_queue_policy.is_enabled);
  if (old_task_queue_policy.priority != new_task_queue_policy.priority)
    task_queue->SetQueuePriority(new_task_queue_policy.priority);

  if (old_task_queue_policy.time_domain_type !=
      new_task_queue_policy.time_domain_type) {
    if (new_task_queue_policy.time_domain_type == TimeDomainType::THROTTLED) {
      throttling_helper_->IncreaseThrottleRefCount(task_queue);
    } else if (old_task_queue_policy.time_domain_type ==
               TimeDomainType::THROTTLED) {
      throttling_helper_->DecreaseThrottleRefCount(task_queue);
    }
  }
}

bool RendererSchedulerImpl::InputSignalsSuggestGestureInProgress(
    base::TimeTicks now) const {
  base::TimeDelta unused_policy_duration;
  switch (ComputeCurrentUseCase(now, &unused_policy_duration)) {
    case UseCase::COMPOSITOR_GESTURE:
    case UseCase::MAIN_THREAD_GESTURE:
    case UseCase::SYNCHRONIZED_GESTURE:
    case UseCase::TOUCHSTART:
      return true;

    default:
      break;
  }
  return false;
}

RendererSchedulerImpl::UseCase RendererSchedulerImpl::ComputeCurrentUseCase(
    base::TimeTicks now,
    base::TimeDelta* expected_use_case_duration) const {
  any_thread_lock_.AssertAcquired();
  // Special case for flings. This is needed because we don't get notification
  // of a fling ending (although we do for cancellation).
  if (AnyThread().fling_compositor_escalation_deadline > now) {
    *expected_use_case_duration =
        AnyThread().fling_compositor_escalation_deadline - now;
    return UseCase::COMPOSITOR_GESTURE;
  }
  // Above all else we want to be responsive to user input.
  *expected_use_case_duration =
      AnyThread().user_model.TimeLeftInUserGesture(now);
  if (*expected_use_case_duration > base::TimeDelta()) {
    // Has a gesture been fully established?
    if (AnyThread().awaiting_touch_start_response) {
      // No, so arrange for compositor tasks to be run at the highest priority.
      return UseCase::TOUCHSTART;
    }

    // Yes a gesture has been established.  Based on how the gesture is handled
    // we need to choose between one of three use cases:
    // 1. COMPOSITOR_GESTURE where the gesture is processed only on the
    //    compositor thread.
    // 2. MAIN_THREAD_GESTURE where the gesture is processed only on the main
    //    thread.
    // 3. SYNCHRONIZED_GESTURE where the gesture is processed on both threads.
    // TODO(skyostil): Consider removing in_idle_period_ and
    // HadAnIdlePeriodRecently() unless we need them here.
    if (AnyThread().last_gesture_was_compositor_driven) {
      if (AnyThread().begin_main_frame_on_critical_path) {
        return UseCase::SYNCHRONIZED_GESTURE;
      } else {
        return UseCase::COMPOSITOR_GESTURE;
      }
    }
    return UseCase::MAIN_THREAD_GESTURE;
  }

  // TODO(alexclarke): return UseCase::LOADING if signals suggest the system is
  // in the initial 1s of RAIL loading.
  return UseCase::NONE;
}

base::TimeDelta RendererSchedulerImpl::EstimateLongestJankFreeTaskDuration()
    const {
  switch (MainThreadOnly().current_use_case) {
    case UseCase::TOUCHSTART:
    case UseCase::COMPOSITOR_GESTURE:
    case UseCase::LOADING:
    case UseCase::NONE:
      return base::TimeDelta::FromMilliseconds(kRailsResponseTimeMillis);

    case UseCase::MAIN_THREAD_GESTURE:
    case UseCase::SYNCHRONIZED_GESTURE:
      return MainThreadOnly().idle_time_estimator.GetExpectedIdleDuration(
          MainThreadOnly().compositor_frame_interval);

    default:
      NOTREACHED();
      return base::TimeDelta::FromMilliseconds(kRailsResponseTimeMillis);
  }
}

bool RendererSchedulerImpl::CanEnterLongIdlePeriod(
    base::TimeTicks now,
    base::TimeDelta* next_long_idle_period_delay_out) {
  helper_.CheckOnValidThread();

  MaybeUpdatePolicy();
  if (MainThreadOnly().current_use_case == UseCase::TOUCHSTART) {
    // Don't start a long idle task in touch start priority, try again when
    // the policy is scheduled to end.
    *next_long_idle_period_delay_out =
        std::max(base::TimeDelta(),
                 MainThreadOnly().current_policy_expiration_time - now);
    return false;
  }
  return true;
}

SchedulerHelper* RendererSchedulerImpl::GetSchedulerHelperForTesting() {
  return &helper_;
}

TaskCostEstimator*
RendererSchedulerImpl::GetLoadingTaskCostEstimatorForTesting() {
  return &MainThreadOnly().loading_task_cost_estimator;
}

TaskCostEstimator*
RendererSchedulerImpl::GetTimerTaskCostEstimatorForTesting() {
  return &MainThreadOnly().timer_task_cost_estimator;
}

IdleTimeEstimator* RendererSchedulerImpl::GetIdleTimeEstimatorForTesting() {
  return &MainThreadOnly().idle_time_estimator;
}

void RendererSchedulerImpl::SuspendTimerQueue() {
  MainThreadOnly().timer_queue_suspend_count++;
  ForceUpdatePolicy();
#ifndef NDEBUG
  DCHECK(!default_timer_task_runner_->IsQueueEnabled());
  for (const auto& runner : timer_task_runners_) {
    DCHECK(!runner->IsQueueEnabled());
  }
#endif
}

void RendererSchedulerImpl::ResumeTimerQueue() {
  MainThreadOnly().timer_queue_suspend_count--;
  DCHECK_GE(MainThreadOnly().timer_queue_suspend_count, 0);
  ForceUpdatePolicy();
}

void RendererSchedulerImpl::SetTimerQueueSuspensionWhenBackgroundedEnabled(
    bool enabled) {
  // Note that this will only take effect for the next backgrounded signal.
  MainThreadOnly().timer_queue_suspension_when_backgrounded_enabled = enabled;
}

scoped_refptr<base::trace_event::ConvertableToTraceFormat>
RendererSchedulerImpl::AsValue(base::TimeTicks optional_now) const {
  base::AutoLock lock(any_thread_lock_);
  return AsValueLocked(optional_now);
}

scoped_refptr<base::trace_event::ConvertableToTraceFormat>
RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const {
  helper_.CheckOnValidThread();
  any_thread_lock_.AssertAcquired();

  if (optional_now.is_null())
    optional_now = helper_.scheduler_tqm_delegate()->NowTicks();
  scoped_refptr<base::trace_event::TracedValue> state =
      new base::trace_event::TracedValue();

  state->SetBoolean(
      "has_visible_render_widget_with_touch_handler",
      MainThreadOnly().has_visible_render_widget_with_touch_handler);
  state->SetString("current_use_case",
                   UseCaseToString(MainThreadOnly().current_use_case));
  state->SetBoolean("loading_tasks_seem_expensive",
                    MainThreadOnly().loading_tasks_seem_expensive);
  state->SetBoolean("timer_tasks_seem_expensive",
                    MainThreadOnly().timer_tasks_seem_expensive);
  state->SetBoolean("begin_frame_not_expected_soon",
                    MainThreadOnly().begin_frame_not_expected_soon);
  state->SetBoolean("touchstart_expected_soon",
                    MainThreadOnly().touchstart_expected_soon);
  state->SetString("idle_period_state",
                   IdleHelper::IdlePeriodStateToString(
                       idle_helper_.SchedulerIdlePeriodState()));
  state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden);
  state->SetBoolean("have_seen_a_begin_main_frame",
                    MainThreadOnly().have_seen_a_begin_main_frame);
  state->SetBoolean(
      "have_reported_blocking_intervention_in_current_policy",
      MainThreadOnly().have_reported_blocking_intervention_in_current_policy);
  state->SetBoolean(
      "have_reported_blocking_intervention_since_navigation",
      MainThreadOnly().have_reported_blocking_intervention_since_navigation);
  state->SetBoolean("renderer_backgrounded",
                    MainThreadOnly().renderer_backgrounded);
  state->SetBoolean("timer_queue_suspended_when_backgrounded",
                    MainThreadOnly().timer_queue_suspended_when_backgrounded);
  state->SetInteger("timer_queue_suspend_count",
                    MainThreadOnly().timer_queue_suspend_count);
  state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF());
  state->SetDouble(
      "rails_loading_priority_deadline",
      (AnyThread().rails_loading_priority_deadline - base::TimeTicks())
          .InMillisecondsF());
  state->SetDouble(
      "fling_compositor_escalation_deadline",
      (AnyThread().fling_compositor_escalation_deadline - base::TimeTicks())
          .InMillisecondsF());
  state->SetInteger("navigation_task_expected_count",
                    MainThreadOnly().navigation_task_expected_count);
  state->SetDouble("last_idle_period_end_time",
                   (AnyThread().last_idle_period_end_time - base::TimeTicks())
                       .InMillisecondsF());
  state->SetBoolean("awaiting_touch_start_response",
                    AnyThread().awaiting_touch_start_response);
  state->SetBoolean("begin_main_frame_on_critical_path",
                    AnyThread().begin_main_frame_on_critical_path);
  state->SetBoolean("last_gesture_was_compositor_driven",
                    AnyThread().last_gesture_was_compositor_driven);
  state->SetDouble("expected_loading_task_duration",
                   MainThreadOnly()
                       .loading_task_cost_estimator.expected_task_duration()
                       .InMillisecondsF());
  state->SetDouble("expected_timer_task_duration",
                   MainThreadOnly()
                       .timer_task_cost_estimator.expected_task_duration()
                       .InMillisecondsF());
  // TODO(skyostil): Can we somehow trace how accurate these estimates were?
  state->SetDouble(
      "longest_jank_free_task_duration",
      MainThreadOnly().longest_jank_free_task_duration.InMillisecondsF());
  state->SetDouble(
      "compositor_frame_interval",
      MainThreadOnly().compositor_frame_interval.InMillisecondsF());
  state->SetDouble(
      "estimated_next_frame_begin",
      (MainThreadOnly().estimated_next_frame_begin - base::TimeTicks())
          .InMillisecondsF());
  state->SetBoolean("in_idle_period", AnyThread().in_idle_period);
  AnyThread().user_model.AsValueInto(state.get());
  render_widget_scheduler_signals_.AsValueInto(state.get());

  return state;
}

void RendererSchedulerImpl::OnIdlePeriodStarted() {
  base::AutoLock lock(any_thread_lock_);
  AnyThread().in_idle_period = true;
  UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED);
}

void RendererSchedulerImpl::OnIdlePeriodEnded() {
  base::AutoLock lock(any_thread_lock_);
  AnyThread().last_idle_period_end_time =
      helper_.scheduler_tqm_delegate()->NowTicks();
  AnyThread().in_idle_period = false;
  UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED);
}

void RendererSchedulerImpl::AddPendingNavigation() {
  helper_.CheckOnValidThread();
  MainThreadOnly().navigation_task_expected_count++;
  UpdatePolicy();
}

void RendererSchedulerImpl::RemovePendingNavigation() {
  helper_.CheckOnValidThread();
  DCHECK_GT(MainThreadOnly().navigation_task_expected_count, 0);
  if (MainThreadOnly().navigation_task_expected_count > 0)
    MainThreadOnly().navigation_task_expected_count--;
  UpdatePolicy();
}

void RendererSchedulerImpl::OnNavigationStarted() {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
               "RendererSchedulerImpl::OnNavigationStarted");
  base::AutoLock lock(any_thread_lock_);
  AnyThread().rails_loading_priority_deadline =
      helper_.scheduler_tqm_delegate()->NowTicks() +
      base::TimeDelta::FromMilliseconds(
          kRailsInitialLoadingPrioritizationMillis);
  ResetForNavigationLocked();
}

bool RendererSchedulerImpl::HadAnIdlePeriodRecently(base::TimeTicks now) const {
  return (now - AnyThread().last_idle_period_end_time) <=
         base::TimeDelta::FromMilliseconds(
             kIdlePeriodStarvationThresholdMillis);
}

void RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded() {
  DCHECK(MainThreadOnly().renderer_backgrounded);
  if (MainThreadOnly().timer_queue_suspended_when_backgrounded)
    return;

  MainThreadOnly().timer_queue_suspended_when_backgrounded = true;
  ForceUpdatePolicy();
}

void RendererSchedulerImpl::ResumeTimerQueueWhenForegrounded() {
  DCHECK(!MainThreadOnly().renderer_backgrounded);
  if (!MainThreadOnly().timer_queue_suspended_when_backgrounded)
    return;

  MainThreadOnly().timer_queue_suspended_when_backgrounded = false;
  ForceUpdatePolicy();
}

void RendererSchedulerImpl::ResetForNavigationLocked() {
  helper_.CheckOnValidThread();
  any_thread_lock_.AssertAcquired();
  AnyThread().user_model.Reset(helper_.scheduler_tqm_delegate()->NowTicks());
  AnyThread().have_seen_touchstart = false;
  MainThreadOnly().loading_task_cost_estimator.Clear();
  MainThreadOnly().timer_task_cost_estimator.Clear();
  MainThreadOnly().idle_time_estimator.Clear();
  MainThreadOnly().have_seen_a_begin_main_frame = false;
  MainThreadOnly().have_reported_blocking_intervention_since_navigation = false;
  UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED);
}

double RendererSchedulerImpl::VirtualTimeSeconds() const {
  TaskQueue* current_tq = helper_.CurrentlyExecutingTaskQueue();
  if (current_tq && current_tq->GetTimeDomain()) {
    return (current_tq->GetTimeDomain()->Now() -
            base::TimeTicks::UnixEpoch()).InSecondsF();
  }
  return (helper_.scheduler_tqm_delegate()->NowTicks() -
          base::TimeTicks::UnixEpoch()).InSecondsF();
}

double RendererSchedulerImpl::MonotonicallyIncreasingVirtualTimeSeconds()
    const {
  TaskQueue* current_tq = helper_.CurrentlyExecutingTaskQueue();
  if (current_tq && current_tq->GetTimeDomain()) {
    return current_tq->GetTimeDomain()->Now().ToInternalValue() /
           static_cast<double>(base::Time::kMicrosecondsPerSecond);
  }
  return helper_.scheduler_tqm_delegate()->NowTicks().ToInternalValue() /
          static_cast<double>(base::Time::kMicrosecondsPerSecond);
}

void RendererSchedulerImpl::RegisterTimeDomain(TimeDomain* time_domain) {
  helper_.RegisterTimeDomain(time_domain);
}

void RendererSchedulerImpl::UnregisterTimeDomain(TimeDomain* time_domain) {
  helper_.UnregisterTimeDomain(time_domain);
}

void RendererSchedulerImpl::SetExpensiveTaskBlockingAllowed(bool allowed) {
  MainThreadOnly().expensive_task_blocking_allowed = allowed;
}

base::TickClock* RendererSchedulerImpl::tick_clock() const {
  return helper_.scheduler_tqm_delegate().get();
}

void RendererSchedulerImpl::AddWebViewScheduler(
    WebViewSchedulerImpl* web_view_scheduler) {
  MainThreadOnly().web_view_schedulers_.insert(web_view_scheduler);
}

void RendererSchedulerImpl::RemoveWebViewScheduler(
    WebViewSchedulerImpl* web_view_scheduler) {
  DCHECK(MainThreadOnly().web_view_schedulers_.find(web_view_scheduler) !=
         MainThreadOnly().web_view_schedulers_.end());
  MainThreadOnly().web_view_schedulers_.erase(web_view_scheduler);
}

void RendererSchedulerImpl::BroadcastConsoleWarning(
    const std::string& message) {
  helper_.CheckOnValidThread();
  for (auto& web_view_scheduler : MainThreadOnly().web_view_schedulers_)
    web_view_scheduler->AddConsoleWarning(message);
}

void RendererSchedulerImpl::OnTriedToExecuteBlockedTask(
    const TaskQueue& queue,
    const base::PendingTask& task) {
  if (!MainThreadOnly().have_reported_blocking_intervention_in_current_policy) {
    MainThreadOnly().have_reported_blocking_intervention_in_current_policy =
        true;
    TRACE_TASK_EXECUTION("RendererSchedulerImpl::TaskBlocked", task);
  }

  if (!MainThreadOnly().have_reported_blocking_intervention_since_navigation) {
    {
      base::AutoLock lock(any_thread_lock_);
      if (!AnyThread().have_seen_touchstart)
        return;
    }
    MainThreadOnly().have_reported_blocking_intervention_since_navigation =
        true;
    BroadcastConsoleWarning(
        "Deferred long-running timer task(s) to improve scrolling smoothness. "
        "See crbug.com/574343.");
  }
}

}  // namespace scheduler
