| 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), |
| 220 m_intersectWithRemoteAncestors(intersectWithRemoteAncestors) { |
| 207 switch (rootMargin.size()) { | 221 switch (rootMargin.size()) { |
| 208 case 0: | 222 case 0: |
| 209 break; | 223 break; |
| 210 case 1: | 224 case 1: |
| 211 m_topMargin = m_rightMargin = m_bottomMargin = m_leftMargin = | 225 m_topMargin = m_rightMargin = m_bottomMargin = m_leftMargin = |
| 212 rootMargin[0]; | 226 rootMargin[0]; |
| 213 break; | 227 break; |
| 214 case 2: | 228 case 2: |
| 215 m_topMargin = m_bottomMargin = rootMargin[0]; | 229 m_topMargin = m_bottomMargin = rootMargin[0]; |
| 216 m_rightMargin = m_leftMargin = rootMargin[1]; | 230 m_rightMargin = m_leftMargin = rootMargin[1]; |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 | 441 |
| 428 void IntersectionObserver::deliver() { | 442 void IntersectionObserver::deliver() { |
| 429 if (m_entries.isEmpty()) | 443 if (m_entries.isEmpty()) |
| 430 return; | 444 return; |
| 431 | 445 |
| 432 HeapVector<Member<IntersectionObserverEntry>> entries; | 446 HeapVector<Member<IntersectionObserverEntry>> entries; |
| 433 entries.swap(m_entries); | 447 entries.swap(m_entries); |
| 434 m_callback->handleEvent(entries, *this); | 448 m_callback->handleEvent(entries, *this); |
| 435 } | 449 } |
| 436 | 450 |
| 451 void IntersectionObserver::intersectWithRemoteAncestorsIfNeeded( |
| 452 LayoutRect& rect) { |
| 453 if (m_intersectWithRemoteAncestors) { |
| 454 Document* root = toDocument(rootNode()); |
| 455 if (root->view()) { |
| 456 LayoutRect viewportIntersectionRect( |
| 457 root->view()->remoteViewportIntersection()); |
| 458 rect.intersect(viewportIntersectionRect); |
| 459 } |
| 460 } |
| 461 } |
| 462 |
| 437 DEFINE_TRACE(IntersectionObserver) { | 463 DEFINE_TRACE(IntersectionObserver) { |
| 438 visitor->template registerWeakMembers< | 464 visitor->template registerWeakMembers< |
| 439 IntersectionObserver, &IntersectionObserver::clearWeakMembers>(this); | 465 IntersectionObserver, &IntersectionObserver::clearWeakMembers>(this); |
| 440 visitor->trace(m_callback); | 466 visitor->trace(m_callback); |
| 441 visitor->trace(m_observations); | 467 visitor->trace(m_observations); |
| 442 visitor->trace(m_entries); | 468 visitor->trace(m_entries); |
| 443 } | 469 } |
| 444 | 470 |
| 445 } // namespace blink | 471 } // namespace blink |
| OLD | NEW |