/*
 * Copyright (C) 2010 Julien Chaffraix <jchaffraix@webkit.org>
 * All right reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_XMLHTTPREQUEST_XML_HTTP_REQUEST_PROGRESS_EVENT_THROTTLE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_XMLHTTPREQUEST_XML_HTTP_REQUEST_PROGRESS_EVENT_THROTTLE_H_

#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"

namespace blink {

class Event;
class XMLHttpRequest;

// This class implements the XHR2 ProgressEvent dispatching:
//   "dispatch a progress event named progress about every 50ms or for every
//   byte received, whichever is least frequent".
//
// readystatechange events also go through this class since ProgressEvents and
// readystatechange events affect each other.
//
// In the comments for this class:
// - "progress" event means an event named "progress"
// - ProgressEvent means an event using the ProgressEvent interface defined in
//   the spec.
class XMLHttpRequestProgressEventThrottle final
    : public GarbageCollectedFinalized<XMLHttpRequestProgressEventThrottle>,
      public TimerBase {
 public:
  static XMLHttpRequestProgressEventThrottle* Create(
      XMLHttpRequest* event_target) {
    return MakeGarbageCollected<XMLHttpRequestProgressEventThrottle>(
        event_target);
  }

  explicit XMLHttpRequestProgressEventThrottle(XMLHttpRequest*);
  ~XMLHttpRequestProgressEventThrottle() override;

  enum DeferredEventAction {
    kIgnore,
    kClear,
    kFlush,
  };

  // Dispatches a ProgressEvent.
  //
  // Special treatment for events named "progress" is implemented to dispatch
  // them at the required frequency. If this object is suspended, the given
  // ProgressEvent overwrites the existing. I.e. only the latest one gets
  // queued. If the timer is running, this method just updates
  // m_lengthComputable, m_loaded and m_total. They'll be used on next
  // fired() call.
  // For an event named "progress", a readyStateChange will be dispatched
  // as well.
  void DispatchProgressEvent(const AtomicString&,
                             bool length_computable,
                             unsigned long long loaded,
                             unsigned long long total);
  // Dispatches the given event after operation about the "progress" event
  // depending on the value of the ProgressEventAction argument.
  void DispatchReadyStateChangeEvent(Event*, DeferredEventAction);

  void Pause();
  void Unpause();

  // Need to promptly stop this timer when it is deemed finalizable.
  EAGERLY_FINALIZE();
  void Trace(blink::Visitor*);

 private:
  // Dispatches a "progress" progress event and usually a readyStateChange
  // event as well.
  void DispatchProgressProgressEvent(Event*);

  // The main purpose of this class is to throttle the "progress"
  // ProgressEvent dispatching. This class represents such a deferred
  // "progress" ProgressEvent.
  class DeferredEvent {
   public:
    DeferredEvent();
    void Set(bool length_computable,
             unsigned long long loaded,
             unsigned long long total);
    void Clear();
    bool IsSet() const { return is_set_; }
    Event* Take();

   private:
    unsigned long long loaded_;
    unsigned long long total_;
    bool length_computable_;

    bool is_set_;
  };

  void Fired() override;

  Member<XMLHttpRequest> target_;

  // A slot for the deferred "progress" ProgressEvent. When multiple events
  // arrive, only the last one is stored and others are discarded.
  DeferredEvent deferred_;

  // True if any "progress" progress event has been dispatched since
  // |m_target|'s readyState changed.
  bool has_dispatched_progress_progress_event_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_XMLHTTPREQUEST_XML_HTTP_REQUEST_PROGRESS_EVENT_THROTTLE_H_
