OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/dom/IntersectionObserver.h" | 5 #include "core/dom/IntersectionObserver.h" |
6 | 6 |
7 #include "bindings/core/v8/ExceptionState.h" | 7 #include "bindings/core/v8/ExceptionState.h" |
8 #include "core/css/parser/CSSParserTokenRange.h" | 8 #include "core/css/parser/CSSParserTokenRange.h" |
9 #include "core/css/parser/CSSTokenizer.h" | 9 #include "core/css/parser/CSSTokenizer.h" |
10 #include "core/dom/ElementIntersectionObserverData.h" | |
11 #include "core/dom/ExceptionCode.h" | 10 #include "core/dom/ExceptionCode.h" |
12 #include "core/dom/ExecutionContext.h" | 11 #include "core/dom/ExecutionContext.h" |
13 #include "core/dom/IntersectionObserverCallback.h" | 12 #include "core/dom/IntersectionObserverCallback.h" |
14 #include "core/dom/IntersectionObserverController.h" | 13 #include "core/dom/IntersectionObserverController.h" |
15 #include "core/dom/IntersectionObserverEntry.h" | 14 #include "core/dom/IntersectionObserverEntry.h" |
16 #include "core/dom/IntersectionObserverInit.h" | 15 #include "core/dom/IntersectionObserverInit.h" |
| 16 #include "core/dom/NodeIntersectionObserverData.h" |
17 #include "core/html/HTMLFrameOwnerElement.h" | 17 #include "core/html/HTMLFrameOwnerElement.h" |
18 #include "core/layout/LayoutView.h" | 18 #include "core/layout/LayoutView.h" |
19 #include "platform/Timer.h" | 19 #include "platform/Timer.h" |
20 #include "wtf/MainThread.h" | 20 #include "wtf/MainThread.h" |
21 #include <algorithm> | 21 #include <algorithm> |
22 | 22 |
23 namespace blink { | 23 namespace blink { |
24 | 24 |
25 static void parseRootMargin(String rootMarginParameter, Vector<Length>& rootMarg
in, ExceptionState& exceptionState) | 25 static void parseRootMargin(String rootMarginParameter, Vector<Length>& rootMarg
in, ExceptionState& exceptionState) |
26 { | 26 { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 exceptionState.throwTypeError("Threshold values must be between 0 an
d 1"); | 72 exceptionState.throwTypeError("Threshold values must be between 0 an
d 1"); |
73 break; | 73 break; |
74 } | 74 } |
75 } | 75 } |
76 | 76 |
77 std::sort(thresholds.begin(), thresholds.end()); | 77 std::sort(thresholds.begin(), thresholds.end()); |
78 } | 78 } |
79 | 79 |
80 IntersectionObserver* IntersectionObserver::create(const IntersectionObserverIni
t& observerInit, IntersectionObserverCallback& callback, ExceptionState& excepti
onState) | 80 IntersectionObserver* IntersectionObserver::create(const IntersectionObserverIni
t& observerInit, IntersectionObserverCallback& callback, ExceptionState& excepti
onState) |
81 { | 81 { |
82 RefPtrWillBeRawPtr<Element> root = observerInit.root(); | 82 RefPtrWillBeRawPtr<Node> root = observerInit.root(); |
83 if (!root) { | 83 if (!root) { |
84 // TODO(szager): Use Document instead of document element for implicit r
oot. (crbug.com/570538) | 84 // TODO(szager): Use Document instead of document element for implicit r
oot. (crbug.com/570538) |
85 ExecutionContext* context = callback.executionContext(); | 85 ExecutionContext* context = callback.executionContext(); |
86 ASSERT(context->isDocument()); | 86 ASSERT(context->isDocument()); |
87 Frame* mainFrame = toDocument(context)->frame()->tree().top(); | 87 Frame* mainFrame = toDocument(context)->frame()->tree().top(); |
88 if (mainFrame && mainFrame->isLocalFrame()) | 88 if (mainFrame && mainFrame->isLocalFrame()) |
89 root = toLocalFrame(mainFrame)->document()->documentElement(); | 89 root = toLocalFrame(mainFrame)->document(); |
90 } | 90 } |
91 if (!root) { | 91 if (!root) { |
92 exceptionState.throwDOMException(HierarchyRequestError, "Unable to get r
oot element in main frame to track."); | 92 exceptionState.throwDOMException(HierarchyRequestError, "Unable to get r
oot node in main frame to track."); |
93 return nullptr; | 93 return nullptr; |
94 } | 94 } |
95 | 95 |
96 Vector<Length> rootMargin; | 96 Vector<Length> rootMargin; |
97 if (observerInit.hasRootMargin()) | 97 if (observerInit.hasRootMargin()) |
98 parseRootMargin(observerInit.rootMargin(), rootMargin, exceptionState); | 98 parseRootMargin(observerInit.rootMargin(), rootMargin, exceptionState); |
99 if (exceptionState.hadException()) | 99 if (exceptionState.hadException()) |
100 return nullptr; | 100 return nullptr; |
101 | 101 |
102 Vector<float> thresholds; | 102 Vector<float> thresholds; |
103 if (observerInit.hasThreshold()) | 103 if (observerInit.hasThreshold()) |
104 parseThresholds(observerInit.threshold(), thresholds, exceptionState); | 104 parseThresholds(observerInit.threshold(), thresholds, exceptionState); |
105 else | 105 else |
106 thresholds.append(0); | 106 thresholds.append(0); |
107 if (exceptionState.hadException()) | 107 if (exceptionState.hadException()) |
108 return nullptr; | 108 return nullptr; |
109 | 109 |
110 return new IntersectionObserver(callback, *root, rootMargin, thresholds); | 110 return new IntersectionObserver(callback, *root, rootMargin, thresholds); |
111 } | 111 } |
112 | 112 |
113 IntersectionObserver::IntersectionObserver(IntersectionObserverCallback& callbac
k, Element& root, const Vector<Length>& rootMargin, const Vector<float>& thresho
lds) | 113 IntersectionObserver::IntersectionObserver(IntersectionObserverCallback& callbac
k, Node& root, const Vector<Length>& rootMargin, const Vector<float>& thresholds
) |
114 : m_callback(&callback) | 114 : m_callback(&callback) |
115 , m_root(root.ensureIntersectionObserverData().createWeakPtr(&root)) | |
116 , m_thresholds(thresholds) | 115 , m_thresholds(thresholds) |
117 { | 116 { |
| 117 if (root.isDocumentNode()) |
| 118 m_root = toDocument(root).ensureIntersectionObserverData().createWeakPtr
(&root); |
| 119 else |
| 120 m_root = toElement(root).ensureIntersectionObserverData().createWeakPtr(
&root); |
118 switch (rootMargin.size()) { | 121 switch (rootMargin.size()) { |
119 case 0: | 122 case 0: |
120 break; | 123 break; |
121 case 1: | 124 case 1: |
122 m_topMargin = m_rightMargin = m_bottomMargin = m_leftMargin = rootMargin
[0]; | 125 m_topMargin = m_rightMargin = m_bottomMargin = m_leftMargin = rootMargin
[0]; |
123 break; | 126 break; |
124 case 2: | 127 case 2: |
125 m_topMargin = m_bottomMargin = rootMargin[0]; | 128 m_topMargin = m_bottomMargin = rootMargin[0]; |
126 m_rightMargin = m_leftMargin = rootMargin[1]; | 129 m_rightMargin = m_leftMargin = rootMargin[1]; |
127 break; | 130 break; |
128 case 3: | 131 case 3: |
129 m_topMargin = rootMargin[0]; | 132 m_topMargin = rootMargin[0]; |
130 m_rightMargin = m_leftMargin = rootMargin[1]; | 133 m_rightMargin = m_leftMargin = rootMargin[1]; |
131 m_bottomMargin = rootMargin[2]; | 134 m_bottomMargin = rootMargin[2]; |
132 break; | 135 break; |
133 case 4: | 136 case 4: |
134 m_topMargin = rootMargin[0]; | 137 m_topMargin = rootMargin[0]; |
135 m_rightMargin = rootMargin[1]; | 138 m_rightMargin = rootMargin[1]; |
136 m_bottomMargin = rootMargin[2]; | 139 m_bottomMargin = rootMargin[2]; |
137 m_leftMargin = rootMargin[3]; | 140 m_leftMargin = rootMargin[3]; |
138 break; | 141 break; |
139 default: | 142 default: |
140 ASSERT_NOT_REACHED(); | 143 ASSERT_NOT_REACHED(); |
141 break; | 144 break; |
142 } | 145 } |
143 root.document().ensureIntersectionObserverController().addTrackedObserver(*t
his); | 146 root.document().ensureIntersectionObserverController().addTrackedObserver(*t
his); |
144 } | 147 } |
145 | 148 |
146 LayoutObject* IntersectionObserver::rootLayoutObject() | 149 LayoutObject* IntersectionObserver::rootLayoutObject() const |
147 { | 150 { |
148 Element* rootElement = root(); | 151 Node* rootNode = root(); |
149 if (rootElement == rootElement->document().documentElement()) | 152 if (rootNode->isDocumentNode()) |
150 return rootElement->document().layoutView(); | 153 return toDocument(rootNode)->layoutView(); |
151 return rootElement->layoutObject(); | 154 return toElement(rootNode)->layoutObject(); |
152 } | 155 } |
153 | 156 |
154 bool IntersectionObserver::isDescendantOfRoot(const Element* target) const | 157 bool IntersectionObserver::isDescendantOfRoot(const Element* target) const |
155 { | 158 { |
156 // Is m_root an ancestor, through the DOM and frame trees, of target? | 159 // Is m_root an ancestor, through the DOM and frame trees, of target? |
157 Element* rootElement = m_root.get(); | 160 Node* rootNode = root(); |
158 if (!rootElement || !target || target == rootElement) | 161 if (!rootNode || !target || target == rootNode) |
159 return false; | 162 return false; |
160 if (!target->inDocument() || !rootElement->inDocument()) | 163 if (!target->inDocument() || !rootNode->inDocument()) |
161 return false; | 164 return false; |
162 | 165 |
163 Document* rootDocument = &rootElement->document(); | 166 Document* rootDocument = &rootNode->document(); |
164 Document* targetDocument = &target->document(); | 167 Document* targetDocument = &target->document(); |
165 while (targetDocument != rootDocument) { | 168 while (targetDocument != rootDocument) { |
166 target = targetDocument->ownerElement(); | 169 target = targetDocument->ownerElement(); |
167 if (!target) | 170 if (!target) |
168 return false; | 171 return false; |
169 targetDocument = &target->document(); | 172 targetDocument = &target->document(); |
170 } | 173 } |
171 return target->isDescendantOf(rootElement); | 174 if (rootNode->isDocumentNode()) { |
| 175 ASSERT(targetDocument == rootNode); |
| 176 return true; |
| 177 } |
| 178 return target->isDescendantOf(rootNode); |
172 } | 179 } |
173 | 180 |
174 void IntersectionObserver::observe(Element* target, ExceptionState& exceptionSta
te) | 181 void IntersectionObserver::observe(Element* target, ExceptionState& exceptionSta
te) |
175 { | 182 { |
176 checkRootAndDetachIfNeeded(); | 183 checkRootAndDetachIfNeeded(); |
177 if (!m_root) { | 184 if (!m_root) { |
178 exceptionState.throwDOMException(HierarchyRequestError, "Invalid observe
r: root element or containing document has been deleted."); | 185 exceptionState.throwDOMException(HierarchyRequestError, "Invalid observe
r: root element or containing document has been deleted."); |
179 return; | 186 return; |
180 } | 187 } |
181 if (!target) { | 188 if (!target) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 | 334 |
328 DEFINE_TRACE(IntersectionObserver) | 335 DEFINE_TRACE(IntersectionObserver) |
329 { | 336 { |
330 visitor->trace(m_callback); | 337 visitor->trace(m_callback); |
331 visitor->trace(m_root); | 338 visitor->trace(m_root); |
332 visitor->trace(m_observations); | 339 visitor->trace(m_observations); |
333 visitor->trace(m_entries); | 340 visitor->trace(m_entries); |
334 } | 341 } |
335 | 342 |
336 } // namespace blink | 343 } // namespace blink |
OLD | NEW |