Changeset 153406 in webkit
- Timestamp:
- Jul 27, 2013 5:04:14 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r153401 r153406 1 2013-07-27 Alexey Proskuryakov <ap@apple.com> 2 3 Make SuspendableTimer safer 4 https://bugs.webkit.org/show_bug.cgi?id=119127 5 6 Reviewed by Sam Weinig. 7 8 SuspendableTimer now enforces that it stays suspended until resumed (or until stopped 9 and started again). To ensure this, TimerBase is now a private base class, and parts of 10 its interface that clients use are reimplemented with suspend/resume in mind. 11 12 Derived classes are still allowed to override TimerBase virtual functions (notably 13 fired() and alignedFireTime()). 14 15 * dom/DocumentEventQueue.cpp: 16 (WebCore::DocumentEventQueueTimer): Removed an extraneous WTF_MAKE_NONCOPYABLE, 17 TimerBase has it already. 18 (WebCore::DocumentEventQueueTimer::create): Use our normal create() pattern. 19 (WebCore::DocumentEventQueue::DocumentEventQueue): Made the constructor private, accordingly. 20 (WebCore::DocumentEventQueue::cancelEvent): Use SuspendableTimer::cancel(), which 21 is a new name to disambiguate TimerBase::stop() and ActiveDOMObject::stop(). 22 (WebCore::DocumentEventQueue::close): Ditto. 23 24 * page/DOMTimer.cpp: 25 (WebCore::DOMTimer::fired): Now that SuspendableTimer knows whether it's currently 26 suspended, assert that it's not. 27 (WebCore::DOMTimer::didStop): Separated ActiveDOMObject::stop() implementation from 28 additional cleanup, allowing for better SuspendableTimer encapsulation. 29 30 * page/DOMTimer.h: Added FINAL and OVVERIDE specifiers as appropriate. 31 32 * page/SuspendableTimer.h: Added FINAL (and OVERRIDE) qualifiers to ActiveDOMObject 33 methods. A derived class that wants to override current behavior is most likely not 34 a timer, and thus shouldn't be a derived class. 35 (WebCore::SuspendableTimer::isActive): SuspendableTimer with a next fire time is 36 active even if suspended, we shouldn't overwrite its saved data thinking that it's 37 inactive. 38 (WebCore::SuspendableTimer::isSuspended): Exposed to clients (m_suspended is no 39 longer debug only). 40 41 * page/SuspendableTimer.cpp: 42 (WebCore::SuspendableTimer::SuspendableTimer): Updated for new variable names. 43 (WebCore::SuspendableTimer::stop): This is ActiveDOMObject::stop(), which is called 44 before final destruction. We don't track this state directly, but can approximate 45 with setting m_suspended, so even if someone tries to start the timer afterwards, 46 it won't fire. 47 (WebCore::SuspendableTimer::suspend): Updated for new names. 48 (WebCore::SuspendableTimer::resume): Ditto. 49 (WebCore::SuspendableTimer::didStop): No-op default implementation for client hook. 50 (WebCore::SuspendableTimer::cancel): Equivalent of TimerBase::stop(), which also 51 works when suspended. 52 (WebCore::SuspendableTimer::startRepeating): Replacement for TimerBase function with 53 the same name, which works correctly when suspended. We don't want to actually start 54 the timer in this case. 55 (WebCore::SuspendableTimer::startOneShot): Ditto. 56 (WebCore::SuspendableTimer::repeatInterval): Ditto. 57 (WebCore::SuspendableTimer::augmentFireInterval): Ditto. 58 (WebCore::SuspendableTimer::augmentRepeatInterval): Ditto. 59 1 60 2013-07-27 Sam Weinig <sam@webkit.org> 2 61 -
trunk/Source/WebCore/dom/DocumentEventQueue.cpp
r150969 r153406 38 38 namespace WebCore { 39 39 40 class DocumentEventQueueTimer : public SuspendableTimer { 41 WTF_MAKE_NONCOPYABLE(DocumentEventQueueTimer); 40 class DocumentEventQueueTimer FINAL : public SuspendableTimer { 42 41 public: 42 static PassOwnPtr<DocumentEventQueueTimer> create(DocumentEventQueue* eventQueue, ScriptExecutionContext* context) 43 { 44 return adoptPtr(new DocumentEventQueueTimer(eventQueue, context)); 45 } 46 47 private: 43 48 DocumentEventQueueTimer(DocumentEventQueue* eventQueue, ScriptExecutionContext* context) 44 49 : SuspendableTimer(context) 45 50 , m_eventQueue(eventQueue) { } 46 51 47 private: 48 virtual void fired() { m_eventQueue->pendingEventTimerFired(); } 52 virtual void fired() OVERRIDE 53 { 54 ASSERT(!isSuspended()); 55 m_eventQueue->pendingEventTimerFired(); 56 } 57 49 58 DocumentEventQueue* m_eventQueue; 50 59 }; … … 56 65 57 66 DocumentEventQueue::DocumentEventQueue(ScriptExecutionContext* context) 58 : m_pendingEventTimer( adoptPtr(new DocumentEventQueueTimer(this, context)))67 : m_pendingEventTimer(DocumentEventQueueTimer::create(this, context)) 59 68 , m_isClosed(false) 60 69 { … … 104 113 m_queuedEvents.remove(it); 105 114 if (m_queuedEvents.isEmpty()) 106 m_pendingEventTimer-> stop();115 m_pendingEventTimer->cancel(); 107 116 return found; 108 117 } … … 111 120 { 112 121 m_isClosed = true; 113 m_pendingEventTimer-> stop();122 m_pendingEventTimer->cancel(); 114 123 m_queuedEvents.clear(); 115 124 } -
trunk/Source/WebCore/page/DOMTimer.cpp
r152238 r153406 108 108 ScriptExecutionContext* context = scriptExecutionContext(); 109 109 timerNestingLevel = m_nestingLevel; 110 ASSERT(!isSuspended()); 110 111 ASSERT(!context->activeDOMObjectsAreSuspended()); 111 112 UserGestureIndicator gestureIndicator(m_shouldForwardUserGesture ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture); … … 151 152 } 152 153 153 void DOMTimer::stop() 154 { 155 SuspendableTimer::stop(); 154 void DOMTimer::didStop() 155 { 156 156 // Need to release JS objects potentially protected by ScheduledAction 157 157 // because they can form circular references back to the ScriptExecutionContext -
trunk/Source/WebCore/page/DOMTimer.h
r152238 r153406 36 36 class ScheduledAction; 37 37 38 class DOMTimer : public SuspendableTimer {38 class DOMTimer FINAL : public SuspendableTimer { 39 39 public: 40 40 virtual ~DOMTimer(); … … 45 45 46 46 // ActiveDOMObject 47 virtual void contextDestroyed(); 48 virtual void stop(); 47 virtual void contextDestroyed() OVERRIDE; 49 48 50 49 // Adjust to a change in the ScriptExecutionContext's minimum timer interval. … … 55 54 private: 56 55 DOMTimer(ScriptExecutionContext*, PassOwnPtr<ScheduledAction>, int interval, bool singleShot); 57 virtual void fired(); 56 virtual void fired() OVERRIDE; 57 58 // SuspendableTimer 59 virtual void didStop() OVERRIDE; 58 60 59 61 double intervalClampedToMinimum(int timeout, double minimumTimerInterval) const; 60 62 61 63 // Retuns timer fire time rounded to the next multiple of timer alignment interval. 62 virtual double alignedFireTime(double) const ;64 virtual double alignedFireTime(double) const OVERRIDE; 63 65 64 66 int m_timeoutId; -
trunk/Source/WebCore/page/SuspendableTimer.cpp
r146537 r153406 1 1 /* 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.2 * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 34 34 SuspendableTimer::SuspendableTimer(ScriptExecutionContext* context) 35 35 : ActiveDOMObject(context) 36 , m_nextFireInterval(0)37 , m_repeatInterval(0)38 , m_active(false)39 #if !ASSERT_DISABLED40 36 , m_suspended(false) 41 #endif 37 , m_savedNextFireInterval(0) 38 , m_savedRepeatInterval(0) 39 , m_savedIsActive(false) 42 40 { 43 41 } … … 54 52 void SuspendableTimer::stop() 55 53 { 56 TimerBase::stop(); 54 if (!m_suspended) 55 TimerBase::stop(); 56 57 // Make it less likely that SuspendableTimer is accidentally revived and fires after being stopped. 58 // It is not allowed for an ActiveDOMObject to become active again after stop(). 59 m_suspended = true; 60 m_savedIsActive = false; 61 62 didStop(); 57 63 } 58 64 59 65 void SuspendableTimer::suspend(ReasonForSuspension) 60 66 { 61 #if !ASSERT_DISABLED62 67 ASSERT(!m_suspended); 63 68 m_suspended = true; 64 #endif 65 m_ active =isActive();66 if (m_ active) {67 m_ nextFireInterval = nextUnalignedFireInterval();68 m_ repeatInterval = repeatInterval();69 70 m_savedIsActive = TimerBase::isActive(); 71 if (m_savedIsActive) { 72 m_savedNextFireInterval = nextUnalignedFireInterval(); 73 m_savedRepeatInterval = repeatInterval(); 69 74 TimerBase::stop(); 70 75 } … … 73 78 void SuspendableTimer::resume() 74 79 { 75 #if !ASSERT_DISABLED76 80 ASSERT(m_suspended); 77 81 m_suspended = false; 78 #endif 79 if (m_ active)80 start(m_ nextFireInterval, m_repeatInterval);82 83 if (m_savedIsActive) 84 start(m_savedNextFireInterval, m_savedRepeatInterval); 81 85 } 82 86 … … 86 90 } 87 91 92 void SuspendableTimer::didStop() 93 { 94 } 95 96 void SuspendableTimer::cancel() 97 { 98 if (!m_suspended) 99 TimerBase::stop(); 100 else 101 m_suspended = false; 102 } 103 104 void SuspendableTimer::startRepeating(double repeatInterval) 105 { 106 if (!m_suspended) 107 TimerBase::startRepeating(repeatInterval); 108 else { 109 m_savedIsActive = true; 110 m_savedNextFireInterval = repeatInterval; 111 m_savedRepeatInterval = repeatInterval; 112 } 113 } 114 115 void SuspendableTimer::startOneShot(double interval) 116 { 117 if (!m_suspended) 118 TimerBase::startOneShot(interval); 119 else { 120 m_savedIsActive = true; 121 m_savedNextFireInterval = interval; 122 m_savedRepeatInterval = 0; 123 } 124 } 125 126 double SuspendableTimer::repeatInterval() const 127 { 128 if (!m_suspended) 129 return TimerBase::repeatInterval(); 130 if (m_savedIsActive) 131 return m_savedRepeatInterval; 132 return 0; 133 } 134 135 void SuspendableTimer::augmentFireInterval(double delta) 136 { 137 if (!m_suspended) 138 TimerBase::augmentFireInterval(delta); 139 else if (m_savedIsActive) { 140 m_savedNextFireInterval += delta; 141 } else { 142 m_savedIsActive = true; 143 m_savedNextFireInterval = delta; 144 m_savedRepeatInterval = 0; 145 } 146 } 147 148 void SuspendableTimer::augmentRepeatInterval(double delta) 149 { 150 if (!m_suspended) 151 TimerBase::augmentRepeatInterval(delta); 152 else if (m_savedIsActive) { 153 m_savedNextFireInterval += delta; 154 m_savedRepeatInterval += delta; 155 } else { 156 m_savedIsActive = true; 157 m_savedNextFireInterval = delta; 158 m_savedRepeatInterval = delta; 159 } 160 } 161 88 162 } // namespace WebCore -
trunk/Source/WebCore/page/SuspendableTimer.h
r77355 r153406 1 1 /* 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.2 * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 namespace WebCore { 34 34 35 class SuspendableTimer : p ublicTimerBase, public ActiveDOMObject {35 class SuspendableTimer : private TimerBase, public ActiveDOMObject { 36 36 public: 37 37 explicit SuspendableTimer(ScriptExecutionContext*); … … 39 39 40 40 // ActiveDOMObject 41 virtual bool hasPendingActivity() const; 42 virtual void stop(); 43 virtual bool canSuspend() const; 44 virtual void suspend(ReasonForSuspension); 45 virtual void resume(); 41 virtual bool hasPendingActivity() const FINAL OVERRIDE; 42 virtual void stop() FINAL OVERRIDE; 43 virtual bool canSuspend() const FINAL OVERRIDE; 44 virtual void suspend(ReasonForSuspension) FINAL OVERRIDE; 45 virtual void resume() FINAL OVERRIDE; 46 47 // A hook for derived classes to perform cleanup. 48 virtual void didStop(); 49 50 // Part of TimerBase interface used by SuspendableTimer clients, modified to work when suspended. 51 bool isActive() const { return TimerBase::isActive() || (m_suspended && m_savedIsActive); } 52 bool isSuspended() const { return m_suspended; } 53 void startRepeating(double repeatInterval); 54 void startOneShot(double interval); 55 double repeatInterval() const; 56 void augmentFireInterval(double delta); 57 void augmentRepeatInterval(double delta); 58 using TimerBase::didChangeAlignmentInterval; 59 using TimerBase::operator new; 60 using TimerBase::operator delete; 61 62 void cancel(); // Equivalent to TimerBase::stop(), whose name conflicts with ActiveDOMObject::stop(). 46 63 47 64 private: 48 65 virtual void fired() = 0; 49 66 50 double m_nextFireInterval;51 double m_repeatInterval;52 bool m_active;53 #if !ASSERT_DISABLED54 67 bool m_suspended; 55 #endif 68 69 double m_savedNextFireInterval; 70 double m_savedRepeatInterval; 71 bool m_savedIsActive; 56 72 }; 57 73
Note: See TracChangeset
for help on using the changeset viewer.