Bug 867089 - Validate the playbackRate before using it. r=ehsan
[gecko.git] / netwerk / ipc / ChannelEventQueue.h
blob704c6f9b70ea6739f68186832f2f75132c792924
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set sw=2 ts=8 et tw=80 :
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #ifndef mozilla_net_ChannelEventQueue_h
9 #define mozilla_net_ChannelEventQueue_h
11 #include <nsTArray.h>
12 #include <nsAutoPtr.h>
14 class nsISupports;
16 namespace mozilla {
17 namespace net {
19 class ChannelEvent
21 public:
22 ChannelEvent() { MOZ_COUNT_CTOR(ChannelEvent); }
23 virtual ~ChannelEvent() { MOZ_COUNT_DTOR(ChannelEvent); }
24 virtual void Run() = 0;
27 // Workaround for Necko re-entrancy dangers. We buffer IPDL messages in a
28 // queue if still dispatching previous one(s) to listeners/observers.
29 // Otherwise synchronous XMLHttpRequests and/or other code that spins the
30 // event loop (ex: IPDL rpc) could cause listener->OnDataAvailable (for
31 // instance) to be dispatched and called before mListener->OnStartRequest has
32 // completed.
34 class AutoEventEnqueuerBase;
36 class ChannelEventQueue
38 public:
39 ChannelEventQueue(nsISupports *owner)
40 : mForced(false)
41 , mSuspended(false)
42 , mFlushing(false)
43 , mOwner(owner) {}
45 ~ChannelEventQueue() {}
47 // Checks to determine if an IPDL-generated channel event can be processed
48 // immediately, or needs to be queued using Enqueue().
49 inline bool ShouldEnqueue();
51 // Puts IPDL-generated channel event into queue, to be run later
52 // automatically when EndForcedQueueing and/or Resume is called.
53 inline void Enqueue(ChannelEvent* callback);
55 // After StartForcedQueueing is called, ShouldEnqueue() will return true and
56 // no events will be run/flushed until EndForcedQueueing is called.
57 // - Note: queueing may still be required after EndForcedQueueing() (if the
58 // queue is suspended, etc): always call ShouldEnqueue() to determine
59 // whether queueing is needed.
60 inline void StartForcedQueueing();
61 inline void EndForcedQueueing();
63 // Suspend/resume event queue. ShouldEnqueue() will return true and no events
64 // will be run/flushed until resume is called. These should be called when
65 // the channel owning the event queue is suspended/resumed.
66 // - Note: these suspend/resume functions are NOT meant to be called
67 // recursively: call them only at initial suspend, and actual resume).
68 // - Note: Resume flushes the queue and invokes any pending callbacks
69 // immediately--caller must arrange any needed asynchronicity vis a vis
70 // the channel's own Resume() method.
71 inline void Suspend();
72 inline void Resume();
74 private:
75 inline void MaybeFlushQueue();
76 void FlushQueue();
78 nsTArray<nsAutoPtr<ChannelEvent> > mEventQueue;
80 bool mForced;
81 bool mSuspended;
82 bool mFlushing;
84 // Keep ptr to avoid refcount cycle: only grab ref during flushing.
85 nsISupports *mOwner;
87 friend class AutoEventEnqueuer;
90 inline bool
91 ChannelEventQueue::ShouldEnqueue()
93 bool answer = mForced || mSuspended || mFlushing;
95 NS_ABORT_IF_FALSE(answer == true || mEventQueue.IsEmpty(),
96 "Should always enqueue if ChannelEventQueue not empty");
98 return answer;
101 inline void
102 ChannelEventQueue::Enqueue(ChannelEvent* callback)
104 mEventQueue.AppendElement(callback);
107 inline void
108 ChannelEventQueue::StartForcedQueueing()
110 mForced = true;
113 inline void
114 ChannelEventQueue::EndForcedQueueing()
116 mForced = false;
117 MaybeFlushQueue();
120 inline void
121 ChannelEventQueue::Suspend()
123 NS_ABORT_IF_FALSE(!mSuspended,
124 "ChannelEventQueue::Suspend called recursively");
126 mSuspended = true;
129 inline void
130 ChannelEventQueue::Resume()
132 NS_ABORT_IF_FALSE(mSuspended,
133 "ChannelEventQueue::Resume called when not suspended!");
135 mSuspended = false;
136 MaybeFlushQueue();
139 inline void
140 ChannelEventQueue::MaybeFlushQueue()
142 // Don't flush if forced queuing on, we're already being flushed, or
143 // suspended, or there's nothing to flush
144 if (!mForced && !mFlushing && !mSuspended && !mEventQueue.IsEmpty())
145 FlushQueue();
148 // Ensures that ShouldEnqueue() will be true during its lifetime (letting
149 // caller know incoming IPDL msgs should be queued). Flushes the queue when it
150 // goes out of scope.
151 class AutoEventEnqueuer
153 public:
154 AutoEventEnqueuer(ChannelEventQueue &queue) : mEventQueue(queue) {
155 mEventQueue.StartForcedQueueing();
157 ~AutoEventEnqueuer() {
158 mEventQueue.EndForcedQueueing();
160 private:
161 ChannelEventQueue &mEventQueue;
167 #endif