Bug 684627 - Add time limit to nsEventStateManager::IsHandlingUserInput(). r=smaug

This commit is contained in:
Chris Pearce 2011-09-07 08:14:59 +12:00
Родитель 29dff07c3d
Коммит 3bc7160178
6 изменённых файлов: 72 добавлений и 2 удалений

Просмотреть файл

@ -83,6 +83,7 @@ static fp_except_t oldmask = fpsetmask(~allmask);
#include "nsHtml5Parser.h"
#include "nsIFragmentContentSink.h"
#include "nsMathUtils.h"
#include "mozilla/TimeStamp.h"
struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
@ -189,6 +190,7 @@ class nsContentUtils
{
friend class nsAutoScriptBlockerSuppressNodeRemoved;
typedef mozilla::dom::Element Element;
typedef mozilla::TimeDuration TimeDuration;
public:
static nsresult Init();
@ -1720,6 +1722,13 @@ public:
*/
static PRBool IsFullScreenKeyInputRestricted();
/**
* Returns the time limit on handling user input before
* nsEventStateManager::IsHandlingUserInput() stops returning PR_TRUE.
* This enables us to detect long running user-generated event handlers.
*/
static TimeDuration HandlingUserInputTimeout();
static void GetShiftText(nsAString& text);
static void GetControlText(nsAString& text);
static void GetMetaText(nsAString& text);
@ -1887,6 +1896,7 @@ private:
static PRBool sIsFullScreenApiEnabled;
static PRBool sTrustedFullScreenOnly;
static PRBool sFullScreenKeyInputRestricted;
static PRUint32 sHandlingInputTimeout;
static nsHtml5Parser* sHTMLFragmentParser;
static nsIParser* sXMLFragmentParser;

Просмотреть файл

@ -201,6 +201,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#endif
#include "nsDOMTouchEvent.h"
#include "nsIScriptElement.h"
#include "prdtoa.h"
#include "mozilla/Preferences.h"
@ -266,6 +267,8 @@ PRBool nsContentUtils::sIsFullScreenApiEnabled = PR_FALSE;
PRBool nsContentUtils::sTrustedFullScreenOnly = PR_TRUE;
PRBool nsContentUtils::sFullScreenKeyInputRestricted = PR_TRUE;
PRUint32 nsContentUtils::sHandlingInputTimeout = 1000;
nsHtml5Parser* nsContentUtils::sHTMLFragmentParser = nsnull;
nsIParser* nsContentUtils::sXMLFragmentParser = nsnull;
nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nsnull;
@ -319,6 +322,13 @@ class nsSameOriginChecker : public nsIChannelEventSink,
NS_DECL_NSIINTERFACEREQUESTOR
};
/* static */
TimeDuration
nsContentUtils::HandlingUserInputTimeout()
{
return TimeDuration::FromMilliseconds(sHandlingInputTimeout);
}
// static
nsresult
nsContentUtils::Init()
@ -397,6 +407,10 @@ nsContentUtils::Init()
Preferences::AddBoolVarCache(&sFullScreenKeyInputRestricted,
"full-screen-api.key-input-restricted");
Preferences::AddUintVarCache(&sHandlingInputTimeout,
"dom.event.handling-user-input-time-limit",
1000);
sInitialized = PR_TRUE;
return NS_OK;

Просмотреть файл

@ -175,6 +175,8 @@ static PRUint32 gPixelScrollDeltaTimeout = 0;
static nscoord
GetScrollableLineHeight(nsIFrame* aTargetFrame);
TimeStamp nsEventStateManager::sHandlingInputStart;
static inline PRBool
IsMouseEventReal(nsEvent* aEvent)
{

Просмотреть файл

@ -57,6 +57,8 @@
#include "nsFocusManager.h"
#include "nsIDocument.h"
#include "nsEventStates.h"
#include "mozilla/TimeStamp.h"
#include "nsContentUtils.h"
class nsIPresShell;
class nsIDocShell;
@ -80,6 +82,10 @@ class nsEventStateManager : public nsSupportsWeakReference,
{
friend class nsMouseWheelTransaction;
public:
typedef mozilla::TimeStamp TimeStamp;
typedef mozilla::TimeDuration TimeDuration;
nsEventStateManager();
virtual ~nsEventStateManager();
@ -169,16 +175,27 @@ public:
static void StartHandlingUserInput()
{
++sUserInputEventDepth;
if (sUserInputEventDepth == 1) {
sHandlingInputStart = TimeStamp::Now();
}
}
static void StopHandlingUserInput()
{
--sUserInputEventDepth;
if (sUserInputEventDepth == 0) {
sHandlingInputStart = TimeStamp();
}
}
static PRBool IsHandlingUserInput()
{
return sUserInputEventDepth > 0;
if (sUserInputEventDepth <= 0) {
return PR_FALSE;
}
TimeDuration timeout = nsContentUtils::HandlingUserInputTimeout();
return timeout <= TimeDuration(0) ||
(TimeStamp::Now() - sHandlingInputStart) <= timeout;
}
/**
@ -186,7 +203,10 @@ public:
* This includes timers or anything else that is initiated from user input.
* However, mouse hover events are not counted as user input, nor are
* page load events. If this method is called from asynchronously executed code,
* such as during layout reflows, it will return false.
* such as during layout reflows, it will return false. If more time has elapsed
* since the user input than is specified by the
* dom.event.handling-user-input-time-limit pref (default 1 second), this
* function also returns false.
*/
NS_IMETHOD_(PRBool) IsHandlingUserInputExternal() { return IsHandlingUserInput(); }
@ -507,6 +527,8 @@ private:
PRPackedBool m_haveShutdown;
// Time at which we began handling user input.
static TimeStamp sHandlingInputStart;
public:
static nsresult UpdateUserActivityTimer(void);

Просмотреть файл

@ -5,6 +5,7 @@
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=545812">Mozilla Bug 545812</a>
@ -38,6 +39,23 @@ function run() {
prevEnabled = SpecialPowers.getBoolPref("full-screen-api.enabled");
SpecialPowers.setBoolPref("full-screen-api.enabled", true);
// Test requesting full-screen mode in a long-running user-generated event handler.
// The request in the key handler should not be granted.
window.addEventListener("keypress", keyHandler, false);
synthesizeKey("VK_A", {});
}
function keyHandler(event) {
window.removeEventListener("keypress", keyHandler, false);
// Busy loop until 2s has passed. We should then be past the 1 second threshold, and so
// our request for full-screen mode should be rejected.
var end = (new Date()).getTime() + 2000;
while ((new Date()).getTime() < end) {
; // Wait...
}
document.body.mozRequestFullScreen();
prevTrusted = SpecialPowers.getBoolPref("full-screen-api.allow-trusted-requests-only");
// Request full-screen from a non trusted context (this script isn't a user

Просмотреть файл

@ -3351,6 +3351,10 @@ pref("alerts.disableSlidingEffect", false);
pref("full-screen-api.enabled", false);
pref("full-screen-api.allow-trusted-requests-only", true);
pref("full-screen-api.key-input-restricted", true);
// Time limit, in milliseconds, for nsEventStateManager::IsHandlingUserInput().
// Used to detect long running handlers of user-generated events.
pref("dom.event.handling-user-input-time-limit", 1000);
//3D Transforms
pref("layout.3d-transforms.enabled", false);