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/Element.h" | 10 #include "core/dom/Element.h" |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
125 "Threshold values must be numbers between 0 and 1"); | 125 "Threshold values must be numbers between 0 and 1"); |
126 break; | 126 break; |
127 } | 127 } |
128 } | 128 } |
129 | 129 |
130 std::sort(thresholds.begin(), thresholds.end()); | 130 std::sort(thresholds.begin(), thresholds.end()); |
131 } | 131 } |
132 | 132 |
133 // Returns the root Node of a given Document to use as the IntersectionObserver | 133 // Returns the root Node of a given Document to use as the IntersectionObserver |
134 // root when no root is given. | 134 // root when no root is given. |
135 // TODO(szager): it doesn't support RemoteFrames, see https://crbug.com/615156 | |
136 Node* getRootNode(Document* document) { | 135 Node* getRootNode(Document* document) { |
137 Frame* mainFrame = document->frame()->tree().top(); | 136 LocalFrame* rootFrame = document->frame()->localFrameRoot(); |
138 if (mainFrame && mainFrame->isLocalFrame()) | 137 if (rootFrame) |
139 return toLocalFrame(mainFrame)->document(); | 138 return rootFrame->document(); |
140 return nullptr; | 139 return nullptr; |
141 } | 140 } |
142 | 141 |
143 } // anonymous namespace | 142 } // anonymous namespace |
144 | 143 |
145 IntersectionObserver* IntersectionObserver::create( | 144 IntersectionObserver* IntersectionObserver::create( |
146 const IntersectionObserverInit& observerInit, | 145 const IntersectionObserverInit& observerInit, |
147 IntersectionObserverCallback& callback, | 146 IntersectionObserverCallback& callback, |
148 ExceptionState& exceptionState) { | 147 ExceptionState& exceptionState) { |
148 bool intersectWithRemoteAncestors = false; | |
149 Node* root = observerInit.root(); | 149 Node* root = observerInit.root(); |
150 if (!root) { | 150 if (!root) { |
151 ExecutionContext* context = callback.getExecutionContext(); | 151 ExecutionContext* context = callback.getExecutionContext(); |
152 DCHECK(context->isDocument()); | 152 DCHECK(context->isDocument()); |
153 root = getRootNode(toDocument(context)); | 153 root = getRootNode(toDocument(context)); |
154 if (root && (toDocument(context)->frame()->tree().top()->isRemoteFrame() || | |
155 root != | |
156 toLocalFrame(toDocument(context)->frame()->tree().top()) | |
157 ->document())) | |
158 intersectWithRemoteAncestors = true; | |
154 } | 159 } |
155 if (!root) { | 160 if (!root) { |
156 exceptionState.throwDOMException( | 161 exceptionState.throwDOMException( |
157 HierarchyRequestError, | 162 HierarchyRequestError, |
158 "Unable to get root node in main frame to track."); | 163 "Unable to get root node in main frame to track."); |
159 return nullptr; | 164 return nullptr; |
160 } | 165 } |
161 | 166 |
162 Vector<Length> rootMargin; | 167 Vector<Length> rootMargin; |
163 parseRootMargin(observerInit.rootMargin(), rootMargin, exceptionState); | 168 parseRootMargin(observerInit.rootMargin(), rootMargin, exceptionState); |
164 if (exceptionState.hadException()) | 169 if (exceptionState.hadException()) |
165 return nullptr; | 170 return nullptr; |
166 | 171 |
167 Vector<float> thresholds; | 172 Vector<float> thresholds; |
168 parseThresholds(observerInit.threshold(), thresholds, exceptionState); | 173 parseThresholds(observerInit.threshold(), thresholds, exceptionState); |
169 if (exceptionState.hadException()) | 174 if (exceptionState.hadException()) |
170 return nullptr; | 175 return nullptr; |
171 | 176 |
172 return new IntersectionObserver(callback, *root, rootMargin, thresholds); | 177 return new IntersectionObserver(callback, *root, rootMargin, thresholds, |
178 intersectWithRemoteAncestors); | |
173 } | 179 } |
174 | 180 |
175 IntersectionObserver* IntersectionObserver::create( | 181 IntersectionObserver* IntersectionObserver::create( |
176 const Vector<Length>& rootMargin, | 182 const Vector<Length>& rootMargin, |
177 const Vector<float>& thresholds, | 183 const Vector<float>& thresholds, |
178 Document* document, | 184 Document* document, |
179 std::unique_ptr<EventCallback> callback, | 185 std::unique_ptr<EventCallback> callback, |
180 ExceptionState& exceptionState) { | 186 ExceptionState& exceptionState) { |
181 Node* root = getRootNode(document); | 187 Node* root = getRootNode(document); |
188 bool intersectWithRemoteAncestors = false; | |
189 if (root && | |
190 (document->frame()->tree().top()->isRemoteFrame() || | |
191 root != toLocalFrame(document->frame()->tree().top())->document())) | |
192 intersectWithRemoteAncestors = true; | |
182 if (!root) { | 193 if (!root) { |
183 exceptionState.throwDOMException( | 194 exceptionState.throwDOMException( |
184 HierarchyRequestError, | 195 HierarchyRequestError, |
185 "Unable to get root node in main frame to track."); | 196 "Unable to get root node in main frame to track."); |
186 return nullptr; | 197 return nullptr; |
187 } | 198 } |
188 | 199 |
189 IntersectionObserverCallbackImpl* intersectionObserverCallback = | 200 IntersectionObserverCallbackImpl* intersectionObserverCallback = |
190 new IntersectionObserverCallbackImpl(document, std::move(callback)); | 201 new IntersectionObserverCallbackImpl(document, std::move(callback)); |
191 return new IntersectionObserver(*intersectionObserverCallback, *root, | 202 return new IntersectionObserver(*intersectionObserverCallback, *root, |
192 rootMargin, thresholds); | 203 rootMargin, thresholds, |
204 intersectWithRemoteAncestors); | |
193 } | 205 } |
194 | 206 |
195 IntersectionObserver::IntersectionObserver( | 207 IntersectionObserver::IntersectionObserver( |
196 IntersectionObserverCallback& callback, | 208 IntersectionObserverCallback& callback, |
197 Node& root, | 209 Node& root, |
198 const Vector<Length>& rootMargin, | 210 const Vector<Length>& rootMargin, |
199 const Vector<float>& thresholds) | 211 const Vector<float>& thresholds, |
212 bool intersectWithRemoteAncestors) | |
200 : m_callback(&callback), | 213 : m_callback(&callback), |
201 m_root(&root), | 214 m_root(&root), |
202 m_thresholds(thresholds), | 215 m_thresholds(thresholds), |
203 m_topMargin(Fixed), | 216 m_topMargin(Fixed), |
204 m_rightMargin(Fixed), | 217 m_rightMargin(Fixed), |
205 m_bottomMargin(Fixed), | 218 m_bottomMargin(Fixed), |
206 m_leftMargin(Fixed), | 219 m_leftMargin(Fixed), |
207 m_initialState(InitialState::kHidden) { | 220 m_initialState(InitialState::kHidden), |
221 m_intersectWithRemoteAncestors(intersectWithRemoteAncestors) { | |
208 switch (rootMargin.size()) { | 222 switch (rootMargin.size()) { |
209 case 0: | 223 case 0: |
210 break; | 224 break; |
211 case 1: | 225 case 1: |
212 m_topMargin = m_rightMargin = m_bottomMargin = m_leftMargin = | 226 m_topMargin = m_rightMargin = m_bottomMargin = m_leftMargin = |
213 rootMargin[0]; | 227 rootMargin[0]; |
214 break; | 228 break; |
215 case 2: | 229 case 2: |
216 m_topMargin = m_bottomMargin = rootMargin[0]; | 230 m_topMargin = m_bottomMargin = rootMargin[0]; |
217 m_rightMargin = m_leftMargin = rootMargin[1]; | 231 m_rightMargin = m_leftMargin = rootMargin[1]; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
263 return; | 277 return; |
264 | 278 |
265 if (target->ensureIntersectionObserverData().getObservationFor(*this)) | 279 if (target->ensureIntersectionObserverData().getObservationFor(*this)) |
266 return; | 280 return; |
267 bool shouldReportRootBounds = false; | 281 bool shouldReportRootBounds = false; |
268 bool isDOMDescendant = false; | 282 bool isDOMDescendant = false; |
269 LocalFrame* targetFrame = target->document().frame(); | 283 LocalFrame* targetFrame = target->document().frame(); |
270 LocalFrame* rootFrame = m_root->document().frame(); | 284 LocalFrame* rootFrame = m_root->document().frame(); |
271 | 285 |
272 if (target->document() == rootNode()->document()) { | 286 if (target->document() == rootNode()->document()) { |
273 shouldReportRootBounds = true; | 287 if (!m_intersectWithRemoteAncestors) |
288 shouldReportRootBounds = true; | |
274 isDOMDescendant = rootNode()->isShadowIncludingInclusiveAncestorOf(target); | 289 isDOMDescendant = rootNode()->isShadowIncludingInclusiveAncestorOf(target); |
275 } else if (targetFrame && rootFrame) { | 290 } else if (targetFrame && rootFrame) { |
276 shouldReportRootBounds = | 291 shouldReportRootBounds = |
277 targetFrame->securityContext()->getSecurityOrigin()->canAccess( | 292 targetFrame->securityContext()->getSecurityOrigin()->canAccess( |
278 rootFrame->securityContext()->getSecurityOrigin()); | 293 rootFrame->securityContext()->getSecurityOrigin()); |
279 isDOMDescendant = (targetFrame->tree().top() == rootFrame); | 294 isDOMDescendant = (targetFrame->tree().top() == rootFrame); |
280 } | 295 } |
281 | 296 |
282 IntersectionObservation* observation = | 297 IntersectionObservation* observation = |
283 new IntersectionObservation(*this, *target, shouldReportRootBounds); | 298 new IntersectionObservation(*this, *target, shouldReportRootBounds); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 | 453 |
439 void IntersectionObserver::deliver() { | 454 void IntersectionObserver::deliver() { |
440 if (m_entries.isEmpty()) | 455 if (m_entries.isEmpty()) |
441 return; | 456 return; |
442 | 457 |
443 HeapVector<Member<IntersectionObserverEntry>> entries; | 458 HeapVector<Member<IntersectionObserverEntry>> entries; |
444 entries.swap(m_entries); | 459 entries.swap(m_entries); |
445 m_callback->handleEvent(entries, *this); | 460 m_callback->handleEvent(entries, *this); |
446 } | 461 } |
447 | 462 |
463 void IntersectionObserver::intersectWithRemoteAncestorsIfNeeded( | |
szager1
2016/11/16 22:11:22
I agree with Ojan's point that this should be hand
kenrb
2016/11/21 19:37:35
In the most recent PS I have modified mapToVisualR
ojan
2016/11/23 19:14:00
Can we always pass nullptr to mapToVisualRectInAnc
kenrb
2016/11/23 20:07:28
We still need a boolean in the IntersectionObserve
| |
464 LayoutRect& rect) { | |
465 if (m_intersectWithRemoteAncestors) { | |
466 Document* root = toDocument(rootNode()); | |
467 if (root->view()) { | |
468 LayoutRect viewportIntersectionRect( | |
469 root->view()->remoteViewportIntersection()); | |
470 rect.intersect(viewportIntersectionRect); | |
471 } | |
472 } | |
473 } | |
474 | |
448 DEFINE_TRACE(IntersectionObserver) { | 475 DEFINE_TRACE(IntersectionObserver) { |
449 visitor->template registerWeakMembers< | 476 visitor->template registerWeakMembers< |
450 IntersectionObserver, &IntersectionObserver::clearWeakMembers>(this); | 477 IntersectionObserver, &IntersectionObserver::clearWeakMembers>(this); |
451 visitor->trace(m_callback); | 478 visitor->trace(m_callback); |
452 visitor->trace(m_observations); | 479 visitor->trace(m_observations); |
453 visitor->trace(m_entries); | 480 visitor->trace(m_entries); |
454 } | 481 } |
455 | 482 |
456 } // namespace blink | 483 } // namespace blink |
OLD | NEW |