ServiceWorkerContainer does not respond well to network process crash
[WebKit-https.git] / Source / WebCore / dom / EventSender.h
1 /*
2  * Copyright (C) 2012 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "Timer.h"
29 #include <wtf/Vector.h>
30 #include <wtf/WeakPtr.h>
31
32 namespace WebCore {
33
34 class Page;
35
36 template<typename T> class EventSender {
37     WTF_MAKE_NONCOPYABLE(EventSender); WTF_MAKE_FAST_ALLOCATED;
38 public:
39     explicit EventSender(const AtomString& eventType);
40
41     const AtomString& eventType() const { return m_eventType; }
42     void dispatchEventSoon(T&);
43     void cancelEvent(T&);
44     void dispatchPendingEvents(Page*);
45
46 #if ASSERT_ENABLED
47     bool hasPendingEvents(T& sender) const
48     {
49         return m_dispatchSoonList.find(&sender) != notFound || m_dispatchingList.find(&sender) != notFound;
50     }
51 #endif
52
53 private:
54     void timerFired() { dispatchPendingEvents(nullptr); }
55
56     AtomString m_eventType;
57     Timer m_timer;
58     Vector<WeakPtr<T>> m_dispatchSoonList;
59     Vector<WeakPtr<T>> m_dispatchingList;
60 };
61
62 template<typename T> EventSender<T>::EventSender(const AtomString& eventType)
63     : m_eventType(eventType)
64     , m_timer(*this, &EventSender::timerFired)
65 {
66 }
67
68 template<typename T> void EventSender<T>::dispatchEventSoon(T& sender)
69 {
70     m_dispatchSoonList.append(sender);
71     if (!m_timer.isActive())
72         m_timer.startOneShot(0_s);
73 }
74
75 template<typename T> void EventSender<T>::cancelEvent(T& sender)
76 {
77     // Remove instances of this sender from both lists.
78     // Use loops because we allow multiple instances to get into the lists.
79     for (auto& event : m_dispatchSoonList) {
80         if (event == &sender)
81             event = nullptr;
82     }
83     for (auto& event : m_dispatchingList) {
84         if (event == &sender)
85             event = nullptr;
86     }
87 }
88
89 template<typename T> void EventSender<T>::dispatchPendingEvents(Page* page)
90 {
91     // Need to avoid re-entering this function; if new dispatches are
92     // scheduled before the parent finishes processing the list, they
93     // will set a timer and eventually be processed.
94     if (!m_dispatchingList.isEmpty())
95         return;
96
97     m_timer.stop();
98
99     m_dispatchSoonList.checkConsistency();
100
101     m_dispatchingList = std::exchange(m_dispatchSoonList, { });
102     for (auto& event : m_dispatchingList) {
103         if (auto sender = event.get()) {
104             event = nullptr;
105             if (!page || sender->document().page() == page)
106                 sender->dispatchPendingEvent(this);
107             else
108                 dispatchEventSoon(*sender);
109         }
110     }
111     m_dispatchingList.clear();
112 }
113
114 } // namespace WebCore