| 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 |