1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ScrollingMetrics.h"
8 #include "mozilla/dom/ContentParent.h"
9 #include "mozilla/StaticPrefs_browser.h"
13 static TimeStamp gScrollingStartTime
;
14 static TimeStamp gScrollingEndTime
;
15 static uint32_t gScrollDistanceCSSPixels
= 0;
16 static dom::InteractionData gScrollingInteraction
= {};
18 void ScrollingMetrics::OnScrollingInteractionEnded() {
19 // We are only interested in content process scrolling
20 if (XRE_IsParentProcess()) {
24 if (!gScrollingStartTime
.IsNull() && !gScrollingEndTime
.IsNull()) {
25 gScrollingInteraction
.mInteractionCount
++;
26 gScrollingInteraction
.mInteractionTimeInMilliseconds
+=
27 static_cast<uint32_t>(
28 (gScrollingEndTime
- gScrollingStartTime
).ToMilliseconds());
30 gScrollingInteraction
.mScrollingDistanceInPixels
+=
31 gScrollDistanceCSSPixels
;
34 gScrollDistanceCSSPixels
= 0;
35 gScrollingStartTime
= TimeStamp();
36 gScrollingEndTime
= TimeStamp();
39 void ScrollingMetrics::OnScrollingInteraction(CSSCoord distanceScrolled
) {
40 // We are only interested in content process scrolling
41 if (XRE_IsParentProcess()) {
45 TimeStamp now
= TimeStamp::Now();
46 if (gScrollingEndTime
.IsNull()) {
47 gScrollingEndTime
= now
;
50 TimeDuration delay
= now
- gScrollingEndTime
;
52 // Has it been too long since the last scroll input event to consider it part
53 // of the same interaction?
55 TimeDuration::FromMilliseconds(
56 StaticPrefs::browser_places_interactions_scrolling_timeout_ms())) {
57 OnScrollingInteractionEnded();
60 if (gScrollingStartTime
.IsNull()) {
61 gScrollingStartTime
= now
;
63 gScrollingEndTime
= now
;
64 gScrollDistanceCSSPixels
+= static_cast<uint32_t>(distanceScrolled
);
67 StaticAutoPtr
<ScrollingMetrics
> ScrollingMetrics::sSingleton
;
69 ScrollingMetrics
* ScrollingMetrics::GetSingleton() {
71 sSingleton
= new ScrollingMetrics
;
74 return sSingleton
.get();
77 struct ScrollingMetricsCollector
{
78 void AppendScrollingMetrics(const std::tuple
<uint32_t, uint32_t>& aMetrics
,
79 dom::ContentParent
* aParent
) {
80 mTimeScrolledMS
+= std::get
<0>(aMetrics
);
81 mDistanceScrolledPixels
+= std::get
<1>(aMetrics
);
84 ~ScrollingMetricsCollector() {
85 mPromiseHolder
.Resolve(
86 std::make_tuple(mTimeScrolledMS
, mDistanceScrolledPixels
), __func__
);
89 uint32_t mTimeScrolledMS
= 0;
90 uint32_t mDistanceScrolledPixels
= 0;
91 MozPromiseHolder
<ScrollingMetrics::ScrollingMetricsPromise
> mPromiseHolder
;
94 auto ScrollingMetrics::CollectScrollingMetricsInternal()
95 -> RefPtr
<ScrollingMetrics::ScrollingMetricsPromise
> {
96 std::shared_ptr
<ScrollingMetricsCollector
> collector
=
97 std::make_shared
<ScrollingMetricsCollector
>();
99 nsTArray
<dom::ContentParent
*> contentParents
;
100 dom::ContentParent::GetAll(contentParents
);
101 for (dom::ContentParent
* parent
: contentParents
) {
102 RefPtr
<dom::ContentParent
> parentRef
= parent
;
103 parent
->SendCollectScrollingMetrics(
104 [collector
, parentRef
](const std::tuple
<uint32_t, uint32_t>& aMetrics
) {
105 collector
->AppendScrollingMetrics(aMetrics
, parentRef
.get());
107 [](mozilla::ipc::ResponseRejectReason
) {});
110 return collector
->mPromiseHolder
.Ensure(__func__
);
113 std::tuple
<uint32_t, uint32_t>
114 ScrollingMetrics::CollectLocalScrollingMetricsInternal() {
115 OnScrollingInteractionEnded();
117 std::tuple
<uint32_t, uint32_t> metrics
=
118 std::make_tuple(gScrollingInteraction
.mInteractionTimeInMilliseconds
,
119 gScrollingInteraction
.mScrollingDistanceInPixels
);
120 gScrollingInteraction
= {};
124 } // namespace mozilla