Changeset 175441 in webkit
- Timestamp:
- Oct 31, 2014 5:12:51 PM (9 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r175439 r175441 1 2014-10-31 Chris Dumez <cdumez@apple.com> 2 3 Support throttling of DOMTimers using nested setTimeout() calls 4 https://bugs.webkit.org/show_bug.cgi?id=138262 5 6 Reviewed by Gavin Barraclough. 7 8 Extend DOMTimers throttling support to timers that are using nested 9 setTimeout() calls instead of a setInterval(). To achieve this, this 10 patch introduces a NestedTimersVector singleton class where nested 11 timers are appended, and for which we potentially update the next 12 firing time, after the parent timer is done executing. 13 14 I have verified this helps on cnn.com for example, which has timers 15 interacting with non-visible plugins that are scheduled using nested 16 setTimeout() calls with a frequency of 150 / 200 ms. 17 18 * page/DOMTimer.cpp: 19 (WebCore::NestedTimersVector::NestedTimersVector): 20 (WebCore::NestedTimersVector::~NestedTimersVector): 21 (WebCore::NestedTimersVector::registerTimer): 22 (WebCore::NestedTimersVector::begin): 23 (WebCore::NestedTimersVector::end): 24 (WebCore::DOMTimer::install): 25 (WebCore::DOMTimer::updateThrottlingStateIfNecessary): 26 (WebCore::DOMTimer::fired): 27 * page/DOMTimer.h: 28 1 29 2014-10-31 Chris Dumez <cdumez@apple.com> 2 30 -
trunk/Source/WebCore/page/DOMTimer.cpp
r174225 r175441 85 85 DOMTimerFireState* DOMTimerFireState::current = nullptr; 86 86 87 struct NestedTimersVector { 88 typedef Vector<DOMTimer*, 1>::const_iterator const_iterator; 89 90 NestedTimersVector(ScriptExecutionContext* context) 91 : shouldSetCurrent(context->isDocument()) 92 { 93 if (shouldSetCurrent) { 94 previous = current; 95 current = this; 96 } 97 } 98 99 ~NestedTimersVector() 100 { 101 if (shouldSetCurrent) 102 current = previous; 103 } 104 105 static NestedTimersVector* current; 106 107 void registerTimer(DOMTimer* timer) 108 { 109 nestedTimers.append(timer); 110 } 111 112 const_iterator begin() const { return nestedTimers.begin(); } 113 const_iterator end() const { return nestedTimers.end(); } 114 115 private: 116 bool shouldSetCurrent; 117 NestedTimersVector* previous; 118 Vector<DOMTimer*, 1> nestedTimers; 119 }; 120 121 NestedTimersVector* NestedTimersVector::current = nullptr; 122 87 123 static inline bool shouldForwardUserGesture(int interval, int nestingLevel) 88 124 { … … 134 170 InspectorInstrumentation::didInstallTimer(context, timer->m_timeoutId, timeout, singleShot); 135 171 172 // Keep track of nested timer installs. 173 if (NestedTimersVector::current) 174 NestedTimersVector::current->registerTimer(timer); 175 136 176 return timer->m_timeoutId; 137 177 } … … 147 187 InspectorInstrumentation::didRemoveTimer(context, timeoutId); 148 188 context->removeTimeout(timeoutId); 189 } 190 191 void DOMTimer::updateThrottlingStateIfNecessary(const DOMTimerFireState& fireState) 192 { 193 if (fireState.scriptDidInteractWithUserObservablePlugin && m_throttleState != ShouldNotThrottle) { 194 m_throttleState = ShouldNotThrottle; 195 updateTimerIntervalIfNecessary(); 196 } else if (fireState.scriptDidInteractWithNonUserObservablePlugin && m_throttleState == Undetermined) { 197 m_throttleState = ShouldThrottle; 198 updateTimerIntervalIfNecessary(); 199 } 149 200 } 150 201 … … 199 250 200 251 InspectorInstrumentation::didFireTimer(cookie); 201 202 if (fireState.scriptDidInteractWithUserObservablePlugin && m_throttleState != ShouldNotThrottle) { 203 m_throttleState = ShouldNotThrottle; 204 updateTimerIntervalIfNecessary(); 205 } else if (fireState.scriptDidInteractWithNonUserObservablePlugin && m_throttleState == Undetermined) { 206 m_throttleState = ShouldThrottle; 207 updateTimerIntervalIfNecessary(); 208 } 252 updateThrottlingStateIfNecessary(fireState); 209 253 210 254 return; … … 230 274 #endif 231 275 276 // Keep track nested timer installs. 277 NestedTimersVector nestedTimers(context); 232 278 m_action->execute(context); 233 279 … … 243 289 244 290 InspectorInstrumentation::didFireTimer(cookie); 291 292 // Check if we should throttle nested single-shot timers. 293 for (auto* timer : nestedTimers) { 294 if (!timer->repeatInterval()) 295 timer->updateThrottlingStateIfNecessary(fireState); 296 } 245 297 246 298 context->setTimerNestingLevel(0); -
trunk/Source/WebCore/page/DOMTimer.h
r173694 r175441 34 34 namespace WebCore { 35 35 36 struct DOMTimerFireState; 36 37 class HTMLPlugInElement; 37 38 class ScheduledAction; … … 55 56 DOMTimer(ScriptExecutionContext*, std::unique_ptr<ScheduledAction>, int interval, bool singleShot); 56 57 double intervalClampedToMinimum() const; 58 void updateThrottlingStateIfNecessary(const DOMTimerFireState&); 57 59 58 60 // SuspendableTimer
Note: See TracChangeset
for help on using the changeset viewer.