Commit a56e7a2a authored by Dmitry Gozman's avatar Dmitry Gozman Committed by Commit Bot

Use Frame's devtools_frame_token_ when using it in trace events

This token is globally-unqiue and has the same value between browser
and renderer. By using it in trace events, one can match frame attribution
for browser and renderer trace events. This will be used to at least
support OOPIFs in DevTools Performance panel in the future.

Bug: 820250
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I932be92154220731dfdc5998614c281b419dc1aa
Reviewed-on: https://chromium-review.googlesource.com/956522
Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543274}
parent 4f966a93
...@@ -553,7 +553,7 @@ void StyleEngine::ClearResolvers() { ...@@ -553,7 +553,7 @@ void StyleEngine::ClearResolvers() {
if (resolver_) { if (resolver_) {
TRACE_EVENT1("blink", "StyleEngine::clearResolver", "frame", TRACE_EVENT1("blink", "StyleEngine::clearResolver", "frame",
GetDocument().GetFrame()); ToTraceValue(GetDocument().GetFrame()));
resolver_->Dispose(); resolver_->Dispose();
resolver_.Clear(); resolver_.Clear();
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "core/dom/DocumentTiming.h" #include "core/dom/DocumentTiming.h"
#include "core/dom/Document.h" #include "core/dom/Document.h"
#include "core/frame/LocalFrame.h"
#include "core/loader/DocumentLoader.h" #include "core/loader/DocumentLoader.h"
#include "core/loader/InteractiveDetector.h" #include "core/loader/InteractiveDetector.h"
#include "platform/instrumentation/tracing/TraceEvent.h" #include "platform/instrumentation/tracing/TraceEvent.h"
...@@ -29,14 +30,16 @@ void DocumentTiming::NotifyDocumentTimingChanged() { ...@@ -29,14 +30,16 @@ void DocumentTiming::NotifyDocumentTimingChanged() {
void DocumentTiming::MarkDomLoading() { void DocumentTiming::MarkDomLoading() {
dom_loading_ = CurrentTimeTicks(); dom_loading_ = CurrentTimeTicks();
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "domLoading", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "domLoading",
dom_loading_, "frame", GetFrame()); dom_loading_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
void DocumentTiming::MarkDomInteractive() { void DocumentTiming::MarkDomInteractive() {
dom_interactive_ = CurrentTimeTicks(); dom_interactive_ = CurrentTimeTicks();
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "domInteractive", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "domInteractive",
dom_interactive_, "frame", GetFrame()); dom_interactive_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
...@@ -44,7 +47,7 @@ void DocumentTiming::MarkDomContentLoadedEventStart() { ...@@ -44,7 +47,7 @@ void DocumentTiming::MarkDomContentLoadedEventStart() {
dom_content_loaded_event_start_ = CurrentTimeTicks(); dom_content_loaded_event_start_ = CurrentTimeTicks();
TRACE_EVENT_MARK_WITH_TIMESTAMP1( TRACE_EVENT_MARK_WITH_TIMESTAMP1(
"blink.user_timing,rail", "domContentLoadedEventStart", "blink.user_timing,rail", "domContentLoadedEventStart",
dom_content_loaded_event_start_, "frame", GetFrame()); dom_content_loaded_event_start_, "frame", ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
...@@ -52,7 +55,7 @@ void DocumentTiming::MarkDomContentLoadedEventEnd() { ...@@ -52,7 +55,7 @@ void DocumentTiming::MarkDomContentLoadedEventEnd() {
dom_content_loaded_event_end_ = CurrentTimeTicks(); dom_content_loaded_event_end_ = CurrentTimeTicks();
TRACE_EVENT_MARK_WITH_TIMESTAMP1( TRACE_EVENT_MARK_WITH_TIMESTAMP1(
"blink.user_timing,rail", "domContentLoadedEventEnd", "blink.user_timing,rail", "domContentLoadedEventEnd",
dom_content_loaded_event_end_, "frame", GetFrame()); dom_content_loaded_event_end_, "frame", ToTraceValue(GetFrame()));
InteractiveDetector* interactive_detector( InteractiveDetector* interactive_detector(
InteractiveDetector::From(*document_)); InteractiveDetector::From(*document_));
if (interactive_detector) { if (interactive_detector) {
...@@ -64,14 +67,16 @@ void DocumentTiming::MarkDomContentLoadedEventEnd() { ...@@ -64,14 +67,16 @@ void DocumentTiming::MarkDomContentLoadedEventEnd() {
void DocumentTiming::MarkDomComplete() { void DocumentTiming::MarkDomComplete() {
dom_complete_ = CurrentTimeTicks(); dom_complete_ = CurrentTimeTicks();
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "domComplete", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "domComplete",
dom_complete_, "frame", GetFrame()); dom_complete_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
void DocumentTiming::MarkFirstLayout() { void DocumentTiming::MarkFirstLayout() {
first_layout_ = CurrentTimeTicks(); first_layout_ = CurrentTimeTicks();
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "firstLayout", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "firstLayout",
first_layout_, "frame", GetFrame()); first_layout_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
......
...@@ -116,7 +116,8 @@ bool WebFrame::Swap(WebFrame* frame) { ...@@ -116,7 +116,8 @@ bool WebFrame::Swap(WebFrame* frame) {
// This trace event is needed to detect the main frame of the // This trace event is needed to detect the main frame of the
// renderer in telemetry metrics. See crbug.com/692112#c11. // renderer in telemetry metrics. See crbug.com/692112#c11.
TRACE_EVENT_INSTANT1("loading", "markAsMainFrame", TRACE_EVENT_INSTANT1("loading", "markAsMainFrame",
TRACE_EVENT_SCOPE_THREAD, "frame", &local_frame); TRACE_EVENT_SCOPE_THREAD, "frame",
ToTraceValue(&local_frame));
} }
} else { } else {
ToWebRemoteFrameImpl(frame)->InitializeCoreFrame(*page, owner, name); ToWebRemoteFrameImpl(frame)->InitializeCoreFrame(*page, owner, name);
......
...@@ -256,6 +256,13 @@ void Frame::UpdateInertIfPossible() { ...@@ -256,6 +256,13 @@ void Frame::UpdateInertIfPossible() {
} }
} }
const CString& Frame::ToTraceValue() {
// token's ToString() is latin1.
if (!trace_value_)
trace_value_ = CString(devtools_frame_token_.ToString().c_str());
return trace_value_.value();
}
Frame::Frame(FrameClient* client, Frame::Frame(FrameClient* client,
Page& page, Page& page,
FrameOwner* owner, FrameOwner* owner,
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "core/page/FrameTree.h" #include "core/page/FrameTree.h"
#include "platform/heap/Handle.h" #include "platform/heap/Handle.h"
#include "platform/wtf/Forward.h" #include "platform/wtf/Forward.h"
#include "platform/wtf/Optional.h"
#include "third_party/WebKit/public/common/feature_policy/feature_policy.h" #include "third_party/WebKit/public/common/feature_policy/feature_policy.h"
namespace blink { namespace blink {
...@@ -199,6 +200,7 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> { ...@@ -199,6 +200,7 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
const base::UnguessableToken& GetDevToolsFrameToken() const { const base::UnguessableToken& GetDevToolsFrameToken() const {
return devtools_frame_token_; return devtools_frame_token_;
} }
const CString& ToTraceValue();
protected: protected:
Frame(FrameClient*, Page&, FrameOwner*, WindowProxyManager*); Frame(FrameClient*, Page&, FrameOwner*, WindowProxyManager*);
...@@ -236,6 +238,7 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> { ...@@ -236,6 +238,7 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
// TODO(sashab): Investigate if this can be represented with m_lifecycle. // TODO(sashab): Investigate if this can be represented with m_lifecycle.
bool is_loading_; bool is_loading_;
base::UnguessableToken devtools_frame_token_; base::UnguessableToken devtools_frame_token_;
WTF::Optional<CString> trace_value_;
}; };
inline FrameClient* Frame::Client() const { inline FrameClient* Frame::Client() const {
...@@ -254,6 +257,14 @@ inline FrameTree& Frame::Tree() const { ...@@ -254,6 +257,14 @@ inline FrameTree& Frame::Tree() const {
// interchangeably. // interchangeably.
DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(Frame) DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(Frame)
// This method should be used instead of Frame* pointer
// in a TRACE_EVENT_XXX macro. Example:
//
// TRACE_EVENT1("category", "event_name", "frame", ToTraceValue(GetFrame()));
static inline CString ToTraceValue(Frame* frame) {
return frame ? frame->ToTraceValue() : CString();
}
} // namespace blink } // namespace blink
#endif // Frame_h #endif // Frame_h
...@@ -1795,7 +1795,7 @@ void WebLocalFrameImpl::InitializeCoreFrame(Page& page, ...@@ -1795,7 +1795,7 @@ void WebLocalFrameImpl::InitializeCoreFrame(Page& page,
// This trace event is needed to detect the main frame of the // This trace event is needed to detect the main frame of the
// renderer in telemetry metrics. See crbug.com/692112#c11. // renderer in telemetry metrics. See crbug.com/692112#c11.
TRACE_EVENT_INSTANT1("loading", "markAsMainFrame", TRACE_EVENT_SCOPE_THREAD, TRACE_EVENT_INSTANT1("loading", "markAsMainFrame", TRACE_EVENT_SCOPE_THREAD,
"frame", frame_); "frame", ToTraceValue(frame_));
} }
} }
......
...@@ -65,7 +65,8 @@ String IdentifiersFactory::SubresourceRequestId(unsigned long identifier) { ...@@ -65,7 +65,8 @@ String IdentifiersFactory::SubresourceRequestId(unsigned long identifier) {
// static // static
String IdentifiersFactory::FrameId(Frame* frame) { String IdentifiersFactory::FrameId(Frame* frame) {
return frame ? IdFromToken(frame->GetDevToolsFrameToken()) : g_empty_string; // Note: this should be equal to ToTraceValue(frame).
return String(ToTraceValue(frame).data());
} }
// static // static
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "core/loader/DocumentLoadTiming.h" #include "core/loader/DocumentLoadTiming.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "core/frame/LocalFrame.h"
#include "core/loader/DocumentLoader.h" #include "core/loader/DocumentLoader.h"
#include "platform/instrumentation/tracing/TraceEvent.h" #include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/weborigin/SecurityOrigin.h" #include "platform/weborigin/SecurityOrigin.h"
...@@ -100,7 +101,8 @@ void DocumentLoadTiming::MarkNavigationStart() { ...@@ -100,7 +101,8 @@ void DocumentLoadTiming::MarkNavigationStart() {
EnsureReferenceTimesSet(); EnsureReferenceTimesSet();
navigation_start_ = reference_monotonic_time_; navigation_start_ = reference_monotonic_time_;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "navigationStart", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "navigationStart",
navigation_start_, "frame", GetFrame()); navigation_start_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
...@@ -111,7 +113,8 @@ void DocumentLoadTiming::SetNavigationStart(TimeTicks navigation_start) { ...@@ -111,7 +113,8 @@ void DocumentLoadTiming::SetNavigationStart(TimeTicks navigation_start) {
EnsureReferenceTimesSet(); EnsureReferenceTimesSet();
navigation_start_ = navigation_start; navigation_start_ = navigation_start;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "navigationStart", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "navigationStart",
navigation_start_, "frame", GetFrame()); navigation_start_, "frame",
ToTraceValue(GetFrame()));
// The reference times are adjusted based on the embedder's navigationStart. // The reference times are adjusted based on the embedder's navigationStart.
DCHECK(!reference_monotonic_time_.is_null()); DCHECK(!reference_monotonic_time_.is_null());
...@@ -140,28 +143,31 @@ void DocumentLoadTiming::AddRedirect(const KURL& redirecting_url, ...@@ -140,28 +143,31 @@ void DocumentLoadTiming::AddRedirect(const KURL& redirecting_url,
void DocumentLoadTiming::SetRedirectStart(TimeTicks redirect_start) { void DocumentLoadTiming::SetRedirectStart(TimeTicks redirect_start) {
redirect_start_ = redirect_start; redirect_start_ = redirect_start;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "redirectStart", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "redirectStart",
redirect_start_, "frame", GetFrame()); redirect_start_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
void DocumentLoadTiming::SetRedirectEnd(TimeTicks redirect_end) { void DocumentLoadTiming::SetRedirectEnd(TimeTicks redirect_end) {
redirect_end_ = redirect_end; redirect_end_ = redirect_end;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "redirectEnd", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "redirectEnd",
redirect_end_, "frame", GetFrame()); redirect_end_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
void DocumentLoadTiming::MarkUnloadEventStart(TimeTicks start_time) { void DocumentLoadTiming::MarkUnloadEventStart(TimeTicks start_time) {
unload_event_start_ = start_time; unload_event_start_ = start_time;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "unloadEventStart", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "unloadEventStart",
start_time, "frame", GetFrame()); start_time, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
void DocumentLoadTiming::MarkUnloadEventEnd(TimeTicks end_time) { void DocumentLoadTiming::MarkUnloadEventEnd(TimeTicks end_time) {
unload_event_end_ = end_time; unload_event_end_ = end_time;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "unloadEventEnd", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "unloadEventEnd",
end_time, "frame", GetFrame()); end_time, "frame", ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
...@@ -172,35 +178,40 @@ void DocumentLoadTiming::MarkFetchStart() { ...@@ -172,35 +178,40 @@ void DocumentLoadTiming::MarkFetchStart() {
void DocumentLoadTiming::SetFetchStart(TimeTicks fetch_start) { void DocumentLoadTiming::SetFetchStart(TimeTicks fetch_start) {
fetch_start_ = fetch_start; fetch_start_ = fetch_start;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "fetchStart", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "fetchStart",
fetch_start_, "frame", GetFrame()); fetch_start_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
void DocumentLoadTiming::SetResponseEnd(TimeTicks response_end) { void DocumentLoadTiming::SetResponseEnd(TimeTicks response_end) {
response_end_ = response_end; response_end_ = response_end;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "responseEnd", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "responseEnd",
response_end_, "frame", GetFrame()); response_end_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
void DocumentLoadTiming::MarkLoadEventStart() { void DocumentLoadTiming::MarkLoadEventStart() {
load_event_start_ = CurrentTimeTicks(); load_event_start_ = CurrentTimeTicks();
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "loadEventStart", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "loadEventStart",
load_event_start_, "frame", GetFrame()); load_event_start_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
void DocumentLoadTiming::MarkLoadEventEnd() { void DocumentLoadTiming::MarkLoadEventEnd() {
load_event_end_ = CurrentTimeTicks(); load_event_end_ = CurrentTimeTicks();
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "loadEventEnd", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "loadEventEnd",
load_event_end_, "frame", GetFrame()); load_event_end_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
void DocumentLoadTiming::MarkRedirectEnd() { void DocumentLoadTiming::MarkRedirectEnd() {
redirect_end_ = CurrentTimeTicks(); redirect_end_ = CurrentTimeTicks();
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "redirectEnd", TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "redirectEnd",
redirect_end_, "frame", GetFrame()); redirect_end_, "frame",
ToTraceValue(GetFrame()));
NotifyDocumentTimingChanged(); NotifyDocumentTimingChanged();
} }
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#include "core/html_names.h" #include "core/html_names.h"
#include "core/input/EventHandler.h" #include "core/input/EventHandler.h"
#include "core/inspector/ConsoleMessage.h" #include "core/inspector/ConsoleMessage.h"
#include "core/inspector/IdentifiersFactory.h"
#include "core/loader/DocumentLoadTiming.h" #include "core/loader/DocumentLoadTiming.h"
#include "core/loader/DocumentLoader.h" #include "core/loader/DocumentLoader.h"
#include "core/loader/FormSubmission.h" #include "core/loader/FormSubmission.h"
...@@ -1802,10 +1803,7 @@ void FrameLoader::RecordLatestRequiredCSP() { ...@@ -1802,10 +1803,7 @@ void FrameLoader::RecordLatestRequiredCSP() {
std::unique_ptr<TracedValue> FrameLoader::ToTracedValue() const { std::unique_ptr<TracedValue> FrameLoader::ToTracedValue() const {
std::unique_ptr<TracedValue> traced_value = TracedValue::Create(); std::unique_ptr<TracedValue> traced_value = TracedValue::Create();
traced_value->BeginDictionary("frame"); traced_value->BeginDictionary("frame");
traced_value->SetString( traced_value->SetString("id_ref", IdentifiersFactory::FrameId(frame_.Get()));
"id_ref", String::Format("0x%" PRIx64,
static_cast<uint64_t>(
reinterpret_cast<uintptr_t>(frame_.Get()))));
traced_value->EndDictionary(); traced_value->EndDictionary();
traced_value->SetBoolean("isLoadingMainFrame", IsLoadingMainFrame()); traced_value->SetBoolean("isLoadingMainFrame", IsLoadingMainFrame());
traced_value->SetString("stateMachine", state_machine_.ToString()); traced_value->SetString("stateMachine", state_machine_.ToString());
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "core/loader/InteractiveDetector.h" #include "core/loader/InteractiveDetector.h"
#include "core/dom/Document.h" #include "core/dom/Document.h"
#include "core/frame/LocalFrame.h"
#include "core/loader/DocumentLoader.h" #include "core/loader/DocumentLoader.h"
#include "platform/Histogram.h" #include "platform/Histogram.h"
#include "platform/instrumentation/tracing/TraceEvent.h" #include "platform/instrumentation/tracing/TraceEvent.h"
...@@ -458,8 +459,8 @@ void InteractiveDetector::OnTimeToInteractiveDetected() { ...@@ -458,8 +459,8 @@ void InteractiveDetector::OnTimeToInteractiveDetected() {
// with whether that happened. // with whether that happened.
TRACE_EVENT_MARK_WITH_TIMESTAMP2( TRACE_EVENT_MARK_WITH_TIMESTAMP2(
"loading,rail", "InteractiveTime", interactive_time_, "frame", "loading,rail", "InteractiveTime", interactive_time_, "frame",
GetSupplementable()->GetFrame(), "had_user_input_before_interactive", ToTraceValue(GetSupplementable()->GetFrame()),
had_user_input_before_interactive); "had_user_input_before_interactive", had_user_input_before_interactive);
// We only send TTI to Performance Timing Observers if FMP was not invalidated // We only send TTI to Performance Timing Observers if FMP was not invalidated
// by input. // by input.
......
...@@ -105,9 +105,9 @@ void PaintTiming::SetFirstMeaningfulPaint( ...@@ -105,9 +105,9 @@ void PaintTiming::SetFirstMeaningfulPaint(
DCHECK(!stamp.is_null()); DCHECK(!stamp.is_null());
DCHECK(!swap_stamp.is_null()); DCHECK(!swap_stamp.is_null());
TRACE_EVENT_MARK_WITH_TIMESTAMP2("loading,rail,devtools.timeline", TRACE_EVENT_MARK_WITH_TIMESTAMP2(
"firstMeaningfulPaint", swap_stamp, "frame", "loading,rail,devtools.timeline", "firstMeaningfulPaint", swap_stamp,
GetFrame(), "afterUserInput", had_input); "frame", ToTraceValue(GetFrame()), "afterUserInput", had_input);
InteractiveDetector* interactive_detector( InteractiveDetector* interactive_detector(
InteractiveDetector::From(*GetSupplementable())); InteractiveDetector::From(*GetSupplementable()));
......
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