Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / UserGestureIndicator.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "platform/UserGestureIndicator.h"
28
29 #include "wtf/Assertions.h"
30 #include "wtf/CurrentTime.h"
31 #include "wtf/MainThread.h"
32
33 namespace WebCore {
34
35 namespace {
36
37 // User gestures timeout in 1 second.
38 const double userGestureTimeout = 1.0;
39
40 // For out of process tokens we allow a 10 second delay.
41 const double userGestureOutOfProcessTimeout = 10.0;
42
43 class GestureToken : public UserGestureToken {
44 public:
45     static PassRefPtr<UserGestureToken> create() { return adoptRef(new GestureToken); }
46
47     virtual ~GestureToken() { }
48     virtual bool hasGestures() const OVERRIDE
49     {
50         // Do not enforce timeouts for gestures which spawned javascript prompts.
51         if (m_consumableGestures < 1 || (WTF::currentTime() - m_timestamp > (m_outOfProcess ? userGestureOutOfProcessTimeout : userGestureTimeout) && !m_javascriptPrompt))
52             return false;
53         return true;
54     }
55
56     void addGesture()
57     {
58         m_consumableGestures++;
59         m_timestamp = WTF::currentTime();
60     }
61
62     void resetTimestamp()
63     {
64         m_timestamp = WTF::currentTime();
65     }
66
67     bool consumeGesture()
68     {
69         if (!m_consumableGestures)
70             return false;
71         m_consumableGestures--;
72         return true;
73     }
74
75     virtual void setOutOfProcess() OVERRIDE
76     {
77         if (WTF::currentTime() - m_timestamp > userGestureTimeout)
78             return;
79         if (hasGestures())
80             m_outOfProcess = true;
81     }
82
83     virtual void setJavascriptPrompt() OVERRIDE
84     {
85         if (WTF::currentTime() - m_timestamp > userGestureTimeout)
86             return;
87         if (hasGestures())
88             m_javascriptPrompt = true;
89     }
90
91 private:
92     GestureToken()
93         : m_consumableGestures(0)
94         , m_timestamp(0)
95         , m_outOfProcess(false)
96         , m_javascriptPrompt(false)
97     {
98     }
99
100     size_t m_consumableGestures;
101     double m_timestamp;
102     bool m_outOfProcess;
103     bool m_javascriptPrompt;
104 };
105
106 }
107
108 static bool isDefinite(ProcessingUserGestureState state)
109 {
110     return state == DefinitelyProcessingNewUserGesture || state == DefinitelyProcessingUserGesture || state == DefinitelyNotProcessingUserGesture;
111 }
112
113 ProcessingUserGestureState UserGestureIndicator::s_state = DefinitelyNotProcessingUserGesture;
114 UserGestureIndicator* UserGestureIndicator::s_topmostIndicator = 0;
115 bool UserGestureIndicator::s_processedUserGestureInPast = false;
116
117 UserGestureIndicator::UserGestureIndicator(ProcessingUserGestureState state)
118     : m_previousState(s_state)
119 {
120     // Silently ignore UserGestureIndicators on non-main threads.
121     if (!isMainThread())
122         return;
123
124     // We overwrite s_state only if the caller is definite about the gesture state.
125     if (isDefinite(state)) {
126         if (!s_topmostIndicator) {
127             s_topmostIndicator = this;
128             m_token = GestureToken::create();
129         } else {
130             m_token = s_topmostIndicator->currentToken();
131         }
132         s_state = state;
133     }
134
135     if (state == DefinitelyProcessingNewUserGesture) {
136         static_cast<GestureToken*>(m_token.get())->addGesture();
137         s_processedUserGestureInPast = true;
138     } else if (state == DefinitelyProcessingUserGesture && s_topmostIndicator == this) {
139         static_cast<GestureToken*>(m_token.get())->addGesture();
140         s_processedUserGestureInPast = true;
141     }
142     ASSERT(isDefinite(s_state));
143 }
144
145 UserGestureIndicator::UserGestureIndicator(PassRefPtr<UserGestureToken> token)
146     : m_previousState(s_state)
147 {
148     // Silently ignore UserGestureIndicators on non-main threads.
149     if (!isMainThread())
150         return;
151
152     if (token) {
153         static_cast<GestureToken*>(token.get())->resetTimestamp();
154         if (!s_topmostIndicator) {
155             s_topmostIndicator = this;
156             m_token = token;
157         } else {
158             m_token = s_topmostIndicator->currentToken();
159             if (static_cast<GestureToken*>(token.get())->hasGestures()) {
160                 static_cast<GestureToken*>(m_token.get())->addGesture();
161                 static_cast<GestureToken*>(token.get())->consumeGesture();
162             }
163         }
164         s_state = DefinitelyProcessingUserGesture;
165     }
166
167     ASSERT(isDefinite(s_state));
168 }
169
170 UserGestureIndicator::~UserGestureIndicator()
171 {
172     if (!isMainThread())
173         return;
174     s_state = m_previousState;
175     if (s_topmostIndicator == this)
176         s_topmostIndicator = 0;
177     ASSERT(isDefinite(s_state));
178 }
179
180 bool UserGestureIndicator::processingUserGesture()
181 {
182     if (!isMainThread())
183         return false;
184     return s_topmostIndicator && static_cast<GestureToken*>(s_topmostIndicator->currentToken())->hasGestures() && (s_state == DefinitelyProcessingNewUserGesture || s_state == DefinitelyProcessingUserGesture);
185 }
186
187 bool UserGestureIndicator::consumeUserGesture()
188 {
189     if (!isMainThread() || !s_topmostIndicator)
190         return false;
191     return static_cast<GestureToken*>(s_topmostIndicator->currentToken())->consumeGesture();
192 }
193
194 UserGestureToken* UserGestureIndicator::currentToken()
195 {
196     if (!isMainThread() || !s_topmostIndicator)
197         return 0;
198     return s_topmostIndicator->m_token.get();
199 }
200
201 void UserGestureIndicator::clearProcessedUserGestureInPast()
202 {
203     if (isMainThread())
204         s_processedUserGestureInPast = false;
205 }
206
207 bool UserGestureIndicator::processedUserGestureInPast()
208 {
209     if (!isMainThread())
210         return false;
211     return s_processedUserGestureInPast;
212 }
213
214 UserGestureIndicatorDisabler::UserGestureIndicatorDisabler()
215     : m_savedState(UserGestureIndicator::s_state)
216     , m_savedIndicator(UserGestureIndicator::s_topmostIndicator)
217 {
218     RELEASE_ASSERT(isMainThread());
219     UserGestureIndicator::s_state = DefinitelyNotProcessingUserGesture;
220     UserGestureIndicator::s_topmostIndicator = 0;
221 }
222
223 UserGestureIndicatorDisabler::~UserGestureIndicatorDisabler()
224 {
225     RELEASE_ASSERT(isMainThread());
226     UserGestureIndicator::s_state = m_savedState;
227     UserGestureIndicator::s_topmostIndicator = m_savedIndicator;
228 }
229
230 }