Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(277)

Side by Side Diff: third_party/WebKit/Source/platform/UserGestureIndicator.cpp

Issue 2401123002: UserGestureIndicator is a mess. Clean it up. (Closed)
Patch Set: Callback cleanup, comments Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Apple Inc. All rights reserved. 2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 12 matching lines...) Expand all
23 * THE POSSIBILITY OF SUCH DAMAGE. 23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #include "platform/UserGestureIndicator.h" 26 #include "platform/UserGestureIndicator.h"
27 27
28 #include "wtf/Assertions.h" 28 #include "wtf/Assertions.h"
29 #include "wtf/CurrentTime.h" 29 #include "wtf/CurrentTime.h"
30 30
31 namespace blink { 31 namespace blink {
32 32
33 namespace {
34
35 // User gestures timeout in 1 second. 33 // User gestures timeout in 1 second.
36 const double userGestureTimeout = 1.0; 34 const double userGestureTimeout = 1.0;
37 35
38 // For out of process tokens we allow a 10 second delay. 36 // For out of process tokens we allow a 10 second delay.
39 const double userGestureOutOfProcessTimeout = 10.0; 37 const double userGestureOutOfProcessTimeout = 10.0;
40 38
41 class GestureToken final : public UserGestureToken { 39 UserGestureToken::UserGestureToken(Status status)
42 WTF_MAKE_NONCOPYABLE(GestureToken); 40 : m_consumableGestures(0),
43 41 m_timestamp(WTF::currentTime()),
44 public: 42 m_timeoutPolicy(Default),
45 static PassRefPtr<UserGestureToken> create() { 43 m_usageCallback(nullptr) {
46 return adoptRef(new GestureToken); 44 if (status == NewGesture || !UserGestureIndicator::currentToken())
47 }
48
49 ~GestureToken() final {}
50
51 bool hasGestures() const override {
52 // Do not enforce timeouts for gestures which spawned javascript prompts or
53 // debugger pause.
54 if (m_consumableGestures < 1 ||
55 (!m_javascriptPrompt && !m_pauseInDebugger &&
56 hasTimedOut(m_outOfProcess ? userGestureOutOfProcessTimeout
57 : userGestureTimeout)))
58 return false;
59 return true;
60 }
61
62 void addGesture() {
63 m_consumableGestures++; 45 m_consumableGestures++;
64 m_timestamp = WTF::currentTime();
65 }
66
67 void resetTimestamp() { m_timestamp = WTF::currentTime(); }
68
69 bool consumeGesture() {
70 if (!m_consumableGestures)
71 return false;
72 m_consumableGestures--;
73 return true;
74 }
75
76 void setOutOfProcess() final {
77 if (!hasTimedOut(userGestureTimeout) && hasGestures())
78 m_outOfProcess = true;
79 }
80
81 void setJavascriptPrompt() final {
82 if (!hasTimedOut(userGestureTimeout) && hasGestures())
83 m_javascriptPrompt = true;
84 }
85
86 void setPauseInDebugger() final {
87 if (!hasTimedOut(userGestureTimeout) && hasGestures())
88 m_pauseInDebugger = true;
89 }
90
91 private:
92 GestureToken()
93 : m_consumableGestures(0),
94 m_timestamp(0),
95 m_outOfProcess(false),
96 m_javascriptPrompt(false),
97 m_pauseInDebugger(false) {}
98
99 bool hasTimedOut(double timeout) const {
100 return WTF::currentTime() - m_timestamp > timeout;
101 }
102
103 size_t m_consumableGestures;
104 double m_timestamp;
105 bool m_outOfProcess;
106 bool m_javascriptPrompt;
107 bool m_pauseInDebugger;
108 };
109
110 bool isDefinite(ProcessingUserGestureState state) {
111 return state == DefinitelyProcessingNewUserGesture ||
112 state == DefinitelyProcessingUserGesture ||
113 state == DefinitelyNotProcessingUserGesture;
114 } 46 }
115 47
116 bool isDefiniteUserGesture(ProcessingUserGestureState state) { 48 bool UserGestureToken::hasGestures() {
117 return state == DefinitelyProcessingNewUserGesture || 49 return m_consumableGestures && !hasTimedOut();
118 state == DefinitelyProcessingUserGesture;
119 } 50 }
120 51
121 } // namespace 52 void UserGestureToken::transferGestureTo(UserGestureToken* other) {
53 if (!hasGestures())
54 return;
55 m_consumableGestures--;
56 other->m_consumableGestures++;
57 other->m_timestamp = WTF::currentTime();
58 }
122 59
123 ProcessingUserGestureState UserGestureIndicator::s_state = 60 bool UserGestureToken::consumeGesture() {
124 DefinitelyNotProcessingUserGesture; 61 if (!m_consumableGestures)
125 UserGestureIndicator* UserGestureIndicator::s_topmostIndicator = 0; 62 return false;
63 m_consumableGestures--;
64 return true;
65 }
66
67 void UserGestureToken::setTimeoutPolicy(TimeoutPolicy policy) {
68 if (!hasTimedOut() && hasGestures() && policy > m_timeoutPolicy)
69 m_timeoutPolicy = policy;
70 }
71
72 bool UserGestureToken::hasTimedOut() const {
73 if (m_timeoutPolicy == HasPaused)
74 return false;
75 double timeout = m_timeoutPolicy == OutOfProcess
76 ? userGestureOutOfProcessTimeout
77 : userGestureTimeout;
78 return WTF::currentTime() - m_timestamp > timeout;
79 }
80
81 void UserGestureToken::setUserGestureUtilizedCallback(
82 UserGestureUtilizedCallback* callback) {
83 CHECK(this == UserGestureIndicator::currentToken());
84 m_usageCallback = callback;
85 }
86
87 void UserGestureToken::userGestureUtilized() {
88 if (m_usageCallback) {
89 m_usageCallback->userGestureUtilized();
90 m_usageCallback = nullptr;
91 }
92 }
93
94 UserGestureToken* UserGestureIndicator::s_rootToken = nullptr;
126 bool UserGestureIndicator::s_processedUserGestureSinceLoad = false; 95 bool UserGestureIndicator::s_processedUserGestureSinceLoad = false;
127 96
128 UserGestureIndicator::UserGestureIndicator( 97 UserGestureIndicator::UserGestureIndicator(PassRefPtr<UserGestureToken> token)
129 ProcessingUserGestureState state, 98 : m_token(token) {
130 UserGestureUtilizedCallback* usageCallback)
131 : m_previousState(DefinitelyNotProcessingUserGesture),
132 m_usageCallback(usageCallback) {
133 // Silently ignore UserGestureIndicators on non-main threads. 99 // Silently ignore UserGestureIndicators on non-main threads.
134 if (!isMainThread()) 100 if (!isMainThread() || !m_token)
135 return; 101 return;
136 102
137 m_previousState = s_state; 103 if (!s_rootToken)
138 104 s_rootToken = m_token.get();
139 // We overwrite s_state only if the caller is definite about the gesture 105 else
140 // state. 106 m_token->transferGestureTo(s_rootToken);
141 if (isDefinite(state)) { 107 s_processedUserGestureSinceLoad = true;
142 if (!s_topmostIndicator) {
143 s_topmostIndicator = this;
144 m_token = GestureToken::create();
145 } else {
146 m_token = currentToken();
147 }
148 s_state = state;
149 }
150
151 if (state == DefinitelyProcessingNewUserGesture) {
152 static_cast<GestureToken*>(m_token.get())->addGesture();
153 s_processedUserGestureSinceLoad = true;
154 } else if (state == DefinitelyProcessingUserGesture &&
155 s_topmostIndicator == this) {
156 static_cast<GestureToken*>(m_token.get())->addGesture();
157 s_processedUserGestureSinceLoad = true;
158 }
159 ASSERT(isDefinite(s_state));
160 }
161
162 UserGestureIndicator::UserGestureIndicator(
163 PassRefPtr<UserGestureToken> token,
164 UserGestureUtilizedCallback* usageCallback)
165 : m_previousState(DefinitelyNotProcessingUserGesture),
166 m_usageCallback(usageCallback) {
167 // Silently ignore UserGestureIndicators on non-main threads.
168 if (!isMainThread())
169 return;
170
171 m_previousState = s_state;
172
173 if (token) {
174 static_cast<GestureToken*>(token.get())->resetTimestamp();
175 if (!s_topmostIndicator) {
176 s_topmostIndicator = this;
177 m_token = token;
178 } else {
179 m_token = currentToken();
180 if (static_cast<GestureToken*>(token.get())->hasGestures()) {
181 static_cast<GestureToken*>(m_token.get())->addGesture();
182 static_cast<GestureToken*>(token.get())->consumeGesture();
183 }
184 }
185 s_state = DefinitelyProcessingUserGesture;
186 }
187
188 ASSERT(isDefinite(s_state));
189 } 108 }
190 109
191 UserGestureIndicator::~UserGestureIndicator() { 110 UserGestureIndicator::~UserGestureIndicator() {
192 if (!isMainThread()) 111 if (isMainThread() && m_token && m_token == s_rootToken) {
193 return; 112 s_rootToken->setUserGestureUtilizedCallback(nullptr);
194 s_state = m_previousState; 113 s_rootToken = nullptr;
195 if (s_topmostIndicator == this) 114 }
196 s_topmostIndicator = nullptr;
197 ASSERT(isDefinite(s_state));
198 } 115 }
199 116
200 // static 117 // static
201 bool UserGestureIndicator::utilizeUserGesture() { 118 bool UserGestureIndicator::utilizeUserGesture() {
202 if (UserGestureIndicator::processingUserGesture()) { 119 if (UserGestureIndicator::processingUserGesture()) {
203 if (s_topmostIndicator->m_usageCallback) { 120 s_rootToken->userGestureUtilized();
204 s_topmostIndicator->m_usageCallback->userGestureUtilized();
205 s_topmostIndicator->m_usageCallback = nullptr;
206 }
207 return true; 121 return true;
208 } 122 }
209 return false; 123 return false;
210 } 124 }
211 125
212 bool UserGestureIndicator::processingUserGesture() { 126 bool UserGestureIndicator::processingUserGesture() {
213 if (auto* token = currentToken()) { 127 if (auto* token = currentToken()) {
214 ASSERT(isMainThread()); 128 ASSERT(isMainThread());
215 return isDefiniteUserGesture(s_state) && 129 return token->hasGestures();
216 static_cast<GestureToken*>(token)->hasGestures();
217 } 130 }
218 131
219 return false; 132 return false;
220 } 133 }
221 134
222 // static 135 // static
223 bool UserGestureIndicator::consumeUserGesture() { 136 bool UserGestureIndicator::consumeUserGesture() {
224 if (auto* token = currentToken()) { 137 if (auto* token = currentToken()) {
225 ASSERT(isMainThread()); 138 ASSERT(isMainThread());
226 if (static_cast<GestureToken*>(token)->consumeGesture()) { 139 if (token->consumeGesture()) {
227 if (s_topmostIndicator->m_usageCallback) { 140 token->userGestureUtilized();
228 s_topmostIndicator->m_usageCallback->userGestureUtilized();
229 s_topmostIndicator->m_usageCallback = nullptr;
230 }
231 return true; 141 return true;
232 } 142 }
233 } 143 }
234 return false; 144 return false;
235 } 145 }
236 146
237 // static 147 // static
238 UserGestureToken* UserGestureIndicator::currentToken() { 148 UserGestureToken* UserGestureIndicator::currentToken() {
239 if (!isMainThread() || !s_topmostIndicator) 149 if (!isMainThread() || !s_rootToken)
240 return nullptr; 150 return nullptr;
241 return s_topmostIndicator->m_token.get(); 151 return s_rootToken;
242 } 152 }
243 153
244 // static 154 // static
245 void UserGestureIndicator::clearProcessedUserGestureSinceLoad() { 155 void UserGestureIndicator::clearProcessedUserGestureSinceLoad() {
246 if (isMainThread()) 156 if (isMainThread())
247 s_processedUserGestureSinceLoad = false; 157 s_processedUserGestureSinceLoad = false;
248 } 158 }
249 159
250 // static 160 // static
251 bool UserGestureIndicator::processedUserGestureSinceLoad() { 161 bool UserGestureIndicator::processedUserGestureSinceLoad() {
252 if (!isMainThread()) 162 if (!isMainThread())
253 return false; 163 return false;
254 return s_processedUserGestureSinceLoad; 164 return s_processedUserGestureSinceLoad;
255 } 165 }
256 166
257 } // namespace blink 167 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698