1/*
2 * Copyright (C) 2016 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#if ENABLE(INTERSECTION_OBSERVER)
29
30#include "ActiveDOMObject.h"
31#include "GCReachableRef.h"
32#include "IntersectionObserverCallback.h"
33#include "IntersectionObserverEntry.h"
34#include "LengthBox.h"
35#include <wtf/RefCounted.h>
36#include <wtf/Variant.h>
37#include <wtf/WeakPtr.h>
38#include <wtf/text/WTFString.h>
39
40namespace WebCore {
41
42class Document;
43class Element;
44
45struct IntersectionObserverRegistration {
46 WeakPtr<IntersectionObserver> observer;
47 Optional<size_t> previousThresholdIndex;
48};
49
50struct IntersectionObserverData {
51 WTF_MAKE_STRUCT_FAST_ALLOCATED;
52
53 // IntersectionObservers for which the element that owns this IntersectionObserverData is the root.
54 // An IntersectionObserver is only owned by a JavaScript wrapper. ActiveDOMObject::hasPendingActivity
55 // is overridden to keep this wrapper alive while the observer has ongoing observations.
56 Vector<WeakPtr<IntersectionObserver>> observers;
57
58 // IntersectionObserverRegistrations for which the element that owns this IntersectionObserverData is the target.
59 Vector<IntersectionObserverRegistration> registrations;
60};
61
62class IntersectionObserver : public RefCounted<IntersectionObserver>, public ActiveDOMObject, public CanMakeWeakPtr<IntersectionObserver> {
63public:
64 struct Init {
65 Element* root { nullptr };
66 String rootMargin;
67 Variant<double, Vector<double>> threshold;
68 };
69
70 static ExceptionOr<Ref<IntersectionObserver>> create(Document&, Ref<IntersectionObserverCallback>&&, Init&&);
71
72 ~IntersectionObserver();
73
74 Document* trackingDocument() const { return m_root ? &m_root->document() : m_implicitRootDocument.get(); }
75
76 Element* root() const { return m_root; }
77 String rootMargin() const;
78 const LengthBox& rootMarginBox() const { return m_rootMargin; }
79 const Vector<double>& thresholds() const { return m_thresholds; }
80 const Vector<Element*> observationTargets() const { return m_observationTargets; }
81
82 void observe(Element&);
83 void unobserve(Element&);
84 void disconnect();
85
86 struct TakenRecords {
87 Vector<Ref<IntersectionObserverEntry>> records;
88 Vector<GCReachableRef<Element>> pendingTargets;
89 };
90 TakenRecords takeRecords();
91
92 void targetDestroyed(Element&);
93 bool hasObservationTargets() const { return m_observationTargets.size(); }
94 void rootDestroyed();
95
96 bool createTimestamp(DOMHighResTimeStamp&) const;
97
98 void appendQueuedEntry(Ref<IntersectionObserverEntry>&&);
99 void notify();
100
101 // ActiveDOMObject.
102 bool hasPendingActivity() const override;
103 const char* activeDOMObjectName() const override;
104 bool canSuspendForDocumentSuspension() const override;
105 void stop() override;
106
107private:
108 IntersectionObserver(Document&, Ref<IntersectionObserverCallback>&&, Element* root, LengthBox&& parsedRootMargin, Vector<double>&& thresholds);
109
110 bool removeTargetRegistration(Element&);
111 void removeAllTargets();
112
113 WeakPtr<Document> m_implicitRootDocument;
114 Element* m_root;
115 LengthBox m_rootMargin;
116 Vector<double> m_thresholds;
117 RefPtr<IntersectionObserverCallback> m_callback;
118 Vector<Element*> m_observationTargets;
119 Vector<GCReachableRef<Element>> m_pendingTargets;
120 Vector<Ref<IntersectionObserverEntry>> m_queuedEntries;
121};
122
123
124} // namespace WebCore
125
126#endif // ENABLE(INTERSECTION_OBSERVER)
127