Bug 720103 - Detect and break create-delete cycles in SMIL timegraphs; r=dholbert

This commit is contained in:
Brian Birtles 2012-02-02 08:58:58 +09:00
Родитель 16c435842a
Коммит b5e8d84620
2 изменённых файлов: 27 добавлений и 7 удалений

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

@ -233,7 +233,7 @@ const PRUint8 nsSMILTimedElement::sMaxNumInstanceTimes = 100;
// Detect if we arrive in some sort of undetected recursive syncbase dependency // Detect if we arrive in some sort of undetected recursive syncbase dependency
// relationship // relationship
const PRUint16 nsSMILTimedElement::sMaxUpdateIntervalRecursionDepth = 20; const PRUint8 nsSMILTimedElement::sMaxUpdateIntervalRecursionDepth = 20;
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Ctor, dtor // Ctor, dtor
@ -252,6 +252,7 @@ nsSMILTimedElement::nsSMILTimedElement()
mSeekState(SEEK_NOT_SEEKING), mSeekState(SEEK_NOT_SEEKING),
mDeferIntervalUpdates(false), mDeferIntervalUpdates(false),
mDoDeferredUpdate(false), mDoDeferredUpdate(false),
mDeleteCount(0),
mUpdateIntervalRecursionDepth(0) mUpdateIntervalRecursionDepth(0)
{ {
mSimpleDur.SetIndefinite(); mSimpleDur.SetIndefinite();
@ -1960,12 +1961,29 @@ nsSMILTimedElement::UpdateCurrentInterval(bool aForceChangeNotice)
if (mElementState == STATE_STARTUP) if (mElementState == STATE_STARTUP)
return; return;
// Although SMIL gives rules for detecting cycles in change notifications,
// some configurations can lead to create-delete-create-delete-etc. cycles
// which SMIL does not consider.
//
// In order to provide consistent behavior in such cases, we detect two
// deletes in a row and then refuse to create any further intervals. That is,
// we say the configuration is invalid.
if (mDeleteCount > 1) {
// When we update the delete count we also set the state to post active, so
// if we're not post active here then something other than
// UpdateCurrentInterval has updated the element state in between and all
// bets are off.
NS_ABORT_IF_FALSE(mElementState == STATE_POSTACTIVE,
"Expected to be in post-active state after performing double delete");
return;
}
// Check that we aren't stuck in infinite recursion updating some syncbase // Check that we aren't stuck in infinite recursion updating some syncbase
// dependencies. Generally such situations should be detected in advance and // dependencies. Generally such situations should be detected in advance and
// the chain broken in a sensible and predictable manner, so if we're hitting // the chain broken in a sensible and predictable manner, so if we're hitting
// this assertion we need to work out how to detect the case that's causing // this assertion we need to work out how to detect the case that's causing
// it. In release builds, just bail out before we overflow the stack. // it. In release builds, just bail out before we overflow the stack.
AutoRestore<PRUint16> depthRestorer(mUpdateIntervalRecursionDepth); AutoRestore<PRUint8> depthRestorer(mUpdateIntervalRecursionDepth);
if (++mUpdateIntervalRecursionDepth > sMaxUpdateIntervalRecursionDepth) { if (++mUpdateIntervalRecursionDepth > sMaxUpdateIntervalRecursionDepth) {
NS_ABORT_IF_FALSE(false, NS_ABORT_IF_FALSE(false,
"Update current interval recursion depth exceeded threshold"); "Update current interval recursion depth exceeded threshold");
@ -2026,6 +2044,8 @@ nsSMILTimedElement::UpdateCurrentInterval(bool aForceChangeNotice)
// sample (along with firing end events, clearing intervals etc.) // sample (along with firing end events, clearing intervals etc.)
RegisterMilestone(); RegisterMilestone();
} else if (mElementState == STATE_WAITING) { } else if (mElementState == STATE_WAITING) {
AutoRestore<PRUint8> deleteCountRestorer(mDeleteCount);
++mDeleteCount;
mElementState = STATE_POSTACTIVE; mElementState = STATE_POSTACTIVE;
ResetCurrentInterval(); ResetCurrentInterval();
} }

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

@ -625,13 +625,13 @@ protected:
// Used to batch updates to the timing model // Used to batch updates to the timing model
class AutoIntervalUpdateBatcher; class AutoIntervalUpdateBatcher;
bool mDeferIntervalUpdates; bool mDeferIntervalUpdates;
bool mDoDeferredUpdate; // Set if an update to the current interval bool mDoDeferredUpdate; // Set if an update to the current interval was
// was requested while mDeferIntervalUpdates // requested while mDeferIntervalUpdates was set
// was set
// Recursion depth checking // Recursion depth checking
PRUint16 mUpdateIntervalRecursionDepth; PRUint8 mDeleteCount;
static const PRUint16 sMaxUpdateIntervalRecursionDepth; PRUint8 mUpdateIntervalRecursionDepth;
static const PRUint8 sMaxUpdateIntervalRecursionDepth;
}; };
#endif // NS_SMILTIMEDELEMENT_H_ #endif // NS_SMILTIMEDELEMENT_H_