Home | History | Annotate | Download | only in xml
      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