1 /* 2 * Copyright (C) 2010 Julien Chaffraix <jchaffraix (at) webkit.org> 3 * All right reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "XMLHttpRequestProgressEventThrottle.h" 29 30 #include "EventTarget.h" 31 #include "XMLHttpRequestProgressEvent.h" 32 33 namespace WebCore { 34 35 const double XMLHttpRequestProgressEventThrottle::minimumProgressEventDispatchingIntervalInSeconds = .05; // 50 ms per specification. 36 37 XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(EventTarget* target) 38 : m_target(target) 39 , m_loaded(0) 40 , m_total(0) 41 , m_suspended(false) 42 { 43 ASSERT(target); 44 } 45 46 XMLHttpRequestProgressEventThrottle::~XMLHttpRequestProgressEventThrottle() 47 { 48 } 49 50 void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total) 51 { 52 ASSERT(!suspended()); 53 if (!isActive()) { 54 // The timer is not active so the least frequent event for now is every byte. 55 // Just go ahead and dispatch the event. 56 57 // We should not have any pending loaded & total information from a previous run. 58 ASSERT(!m_loaded); 59 ASSERT(!m_total); 60 61 dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total)); 62 startRepeating(minimumProgressEventDispatchingIntervalInSeconds); 63 return; 64 } 65 66 // The timer is already active so minimumProgressEventDispatchingIntervalInSeconds is the least frequent event. 67 m_lengthComputable = lengthComputable; 68 m_loaded = loaded; 69 m_total = total; 70 } 71 72 void XMLHttpRequestProgressEventThrottle::dispatchEvent(PassRefPtr<Event> event, ProgressEventAction progressEventAction) 73 { 74 ASSERT(!suspended()); 75 // We should not have any pending events from a previous resume. 76 ASSERT(!m_pausedEvent); 77 78 if (progressEventAction == FlushProgressEvent) 79 flushProgressEvent(); 80 81 m_target->dispatchEvent(event); 82 } 83 84 void XMLHttpRequestProgressEventThrottle::flushProgressEvent() 85 { 86 if (!hasEventToDispatch()) 87 return; 88 89 PassRefPtr<Event> event = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total); 90 m_loaded = 0; 91 m_total = 0; 92 93 // We stop the timer as this is called when no more events are supposed to occur. 94 stop(); 95 96 m_target->dispatchEvent(event); 97 } 98 99 void XMLHttpRequestProgressEventThrottle::dispatchPausedEvent() 100 { 101 ASSERT(!suspended()); 102 if (!m_pausedEvent) 103 return; 104 105 m_target->dispatchEvent(m_pausedEvent); 106 m_pausedEvent = 0; 107 } 108 109 void XMLHttpRequestProgressEventThrottle::fired() 110 { 111 ASSERT(isActive()); 112 ASSERT(!suspended()); 113 ASSERT(!m_pausedEvent); 114 if (!hasEventToDispatch()) { 115 // No progress event was queued since the previous dispatch, we can safely stop the timer. 116 stop(); 117 return; 118 } 119 120 m_target->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total)); 121 m_total = 0; 122 m_loaded = 0; 123 } 124 125 bool XMLHttpRequestProgressEventThrottle::hasEventToDispatch() const 126 { 127 return (m_total || m_loaded) && isActive(); 128 } 129 130 void XMLHttpRequestProgressEventThrottle::suspend() 131 { 132 ASSERT(!m_pausedEvent); 133 134 m_suspended = true; 135 // If we have a progress event waiting to be dispatched, 136 // just queue it. 137 if (hasEventToDispatch()) { 138 m_pausedEvent = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total); 139 m_total = 0; 140 m_loaded = 0; 141 } 142 stop(); 143 } 144 145 void XMLHttpRequestProgressEventThrottle::resume() 146 { 147 ASSERT(!m_loaded); 148 ASSERT(!m_total); 149 150 m_suspended = false; 151 dispatchPausedEvent(); 152 } 153 154 } // namespace WebCore 155