Home | History | Annotate | Download | only in xml
      1 /*
      2  * Copyright (C) 2010 Julien Chaffraix <jchaffraix (at) webkit.org>  All right reserved.
      3  * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
      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 "core/xml/XMLHttpRequestProgressEventThrottle.h"
     29 
     30 #include "core/events/EventTarget.h"
     31 #include "core/xml/XMLHttpRequestProgressEvent.h"
     32 
     33 namespace blink {
     34 
     35 class XMLHttpRequestProgressEventThrottle::DeferredEvent {
     36 public:
     37     DeferredEvent() { clear(); }
     38     void set(bool lengthComputable, unsigned long long loaded, unsigned long long total)
     39     {
     40         m_isDeferred = true;
     41         m_lengthComputable = lengthComputable;
     42         m_loaded = loaded;
     43         m_total = total;
     44     }
     45     void clear()
     46     {
     47         m_isDeferred = false;
     48         m_lengthComputable = false;
     49         m_loaded = 0;
     50         m_total = 0;
     51     }
     52     bool isDeferred() const { return m_isDeferred; }
     53     bool lengthComputable() const { return m_lengthComputable; }
     54     unsigned long long loaded() const { return m_loaded; }
     55     unsigned long long total() const { return m_total; }
     56 
     57 private:
     58     unsigned long long m_loaded;
     59     unsigned long long m_total;
     60     bool m_isDeferred;
     61     bool m_lengthComputable;
     62 };
     63 
     64 const double XMLHttpRequestProgressEventThrottle::minimumProgressEventDispatchingIntervalInSeconds = .05; // 50 ms per specification.
     65 
     66 XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(EventTarget* target)
     67     : m_target(target)
     68     , m_deferred(adoptPtr(new DeferredEvent))
     69 {
     70     ASSERT(target);
     71 }
     72 
     73 XMLHttpRequestProgressEventThrottle::~XMLHttpRequestProgressEventThrottle()
     74 {
     75 }
     76 
     77 void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(const AtomicString& type, bool lengthComputable, unsigned long long loaded, unsigned long long total)
     78 {
     79     // Given that ResourceDispatcher doesn't deliver an event when suspended,
     80     // we don't have to worry about event dispatching while suspended.
     81     if (type != EventTypeNames::progress) {
     82         m_target->dispatchEvent(XMLHttpRequestProgressEvent::create(type, lengthComputable, loaded, total));
     83         return;
     84     }
     85 
     86     if (isActive()) {
     87         m_deferred->set(lengthComputable, loaded, total);
     88     } else {
     89         m_target->dispatchEvent(XMLHttpRequestProgressEvent::create(type, lengthComputable, loaded, total));
     90         startOneShot(minimumProgressEventDispatchingIntervalInSeconds, FROM_HERE);
     91     }
     92 }
     93 
     94 void XMLHttpRequestProgressEventThrottle::dispatchReadyStateChangeEvent(PassRefPtrWillBeRawPtr<Event> event, DeferredEventAction action)
     95 {
     96     // Given that ResourceDispatcher doesn't deliver an event when suspended,
     97     // we don't have to worry about event dispatching while suspended.
     98     if (action == Flush) {
     99         dispatchDeferredEvent();
    100         stop();
    101     } else if (action == Clear) {
    102         m_deferred->clear();
    103         stop();
    104     }
    105 
    106     m_target->dispatchEvent(event);
    107 }
    108 
    109 void XMLHttpRequestProgressEventThrottle::dispatchDeferredEvent()
    110 {
    111     if (m_deferred->isDeferred()) {
    112         m_target->dispatchEvent(XMLHttpRequestProgressEvent::create(EventTypeNames::progress, m_deferred->lengthComputable(), m_deferred->loaded(), m_deferred->total()));
    113         m_deferred->clear();
    114     }
    115 }
    116 
    117 void XMLHttpRequestProgressEventThrottle::fired()
    118 {
    119     if (!m_deferred->isDeferred()) {
    120         // No "progress" event was queued since the previous dispatch, we can
    121         // safely stop the timer.
    122         return;
    123     }
    124 
    125     dispatchDeferredEvent();
    126 
    127     // Watch if another "progress" ProgressEvent arrives in the next 50ms.
    128     startOneShot(minimumProgressEventDispatchingIntervalInSeconds, FROM_HERE);
    129 }
    130 
    131 void XMLHttpRequestProgressEventThrottle::suspend()
    132 {
    133     stop();
    134 }
    135 
    136 void XMLHttpRequestProgressEventThrottle::resume()
    137 {
    138     if (!m_deferred->isDeferred())
    139         return;
    140 
    141     // Do not dispatch events inline here, since ExecutionContext is iterating
    142     // over the list of active DOM objects to resume them, and any activated JS
    143     // event-handler could insert new active DOM objects to the list.
    144     startOneShot(0, FROM_HERE);
    145 }
    146 
    147 void XMLHttpRequestProgressEventThrottle::trace(Visitor* visitor)
    148 {
    149     visitor->trace(m_target);
    150 }
    151 
    152 } // namespace blink
    153