blob: 11bb8aea8da57d5b58a7ea323cdb6065ce08dd13 [file] [log] [blame]
// Copyright 2015 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 "core/dom/FrameRequestCallbackCollection.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/probe/CoreProbes.h"
namespace blink {
FrameRequestCallbackCollection::FrameRequestCallbackCollection(
ExecutionContext* context)
: context_(context) {}
FrameRequestCallbackCollection::CallbackId
FrameRequestCallbackCollection::RegisterCallback(FrameCallback* callback) {
FrameRequestCallbackCollection::CallbackId id = ++next_callback_id_;
callback->SetIsCancelled(false);
callback->SetId(id);
callbacks_.push_back(callback);
TRACE_EVENT_INSTANT1("devtools.timeline", "RequestAnimationFrame",
TRACE_EVENT_SCOPE_THREAD, "data",
InspectorAnimationFrameEvent::Data(context_, id));
probe::AsyncTaskScheduledBreakable(context_, "requestAnimationFrame",
callback);
return id;
}
void FrameRequestCallbackCollection::CancelCallback(CallbackId id) {
for (size_t i = 0; i < callbacks_.size(); ++i) {
if (callbacks_[i]->Id() == id) {
probe::AsyncTaskCanceledBreakable(context_, "cancelAnimationFrame",
callbacks_[i]);
callbacks_.EraseAt(i);
TRACE_EVENT_INSTANT1("devtools.timeline", "CancelAnimationFrame",
TRACE_EVENT_SCOPE_THREAD, "data",
InspectorAnimationFrameEvent::Data(context_, id));
return;
}
}
for (const auto& callback : callbacks_to_invoke_) {
if (callback->Id() == id) {
probe::AsyncTaskCanceledBreakable(context_, "cancelAnimationFrame",
callback);
TRACE_EVENT_INSTANT1("devtools.timeline", "CancelAnimationFrame",
TRACE_EVENT_SCOPE_THREAD, "data",
InspectorAnimationFrameEvent::Data(context_, id));
callback->SetIsCancelled(true);
// will be removed at the end of executeCallbacks()
return;
}
}
}
void FrameRequestCallbackCollection::ExecuteCallbacks(
double high_res_now_ms,
double high_res_now_ms_legacy) {
// First, generate a list of callbacks to consider. Callbacks registered from
// this point on are considered only for the "next" frame, not this one.
DCHECK(callbacks_to_invoke_.IsEmpty());
swap(callbacks_to_invoke_, callbacks_);
for (const auto& callback : callbacks_to_invoke_) {
if (!callback->IsCancelled()) {
TRACE_EVENT1(
"devtools.timeline", "FireAnimationFrame", "data",
InspectorAnimationFrameEvent::Data(context_, callback->Id()));
probe::AsyncTask async_task(context_, callback);
probe::UserCallback probe(context_, "requestAnimationFrame",
AtomicString(), true);
if (callback->GetUseLegacyTimeBase())
callback->Invoke(high_res_now_ms_legacy);
else
callback->Invoke(high_res_now_ms);
}
}
callbacks_to_invoke_.clear();
}
void FrameRequestCallbackCollection::Trace(blink::Visitor* visitor) {
visitor->Trace(callbacks_);
visitor->Trace(callbacks_to_invoke_);
visitor->Trace(context_);
}
void FrameRequestCallbackCollection::TraceWrappers(
const ScriptWrappableVisitor* visitor) const {
for (const auto& callback : callbacks_)
visitor->TraceWrappers(callback);
for (const auto& callback_to_invoke : callbacks_to_invoke_)
visitor->TraceWrappers(callback_to_invoke);
}
FrameRequestCallbackCollection::V8FrameCallback::V8FrameCallback(
V8FrameRequestCallback* callback)
: callback_(callback) {}
void FrameRequestCallbackCollection::V8FrameCallback::Trace(
blink::Visitor* visitor) {
visitor->Trace(callback_);
FrameRequestCallbackCollection::FrameCallback::Trace(visitor);
}
void FrameRequestCallbackCollection::V8FrameCallback::TraceWrappers(
const ScriptWrappableVisitor* visitor) const {
visitor->TraceWrappers(callback_);
FrameRequestCallbackCollection::FrameCallback::TraceWrappers(visitor);
}
void FrameRequestCallbackCollection::V8FrameCallback::Invoke(
double highResTime) {
callback_->InvokeAndReportException(nullptr, highResTime);
}
} // namespace blink