| 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 exceptionState.throwTypeError("Threshold values must be between 0 an
d 1"); | 74 exceptionState.throwTypeError("Threshold values must be between 0 an
d 1"); |
| 75 break; | 75 break; |
| 76 } | 76 } |
| 77 } | 77 } |
| 78 | 78 |
| 79 std::sort(thresholds.begin(), thresholds.end()); | 79 std::sort(thresholds.begin(), thresholds.end()); |
| 80 } | 80 } |
| 81 | 81 |
| 82 IntersectionObserver* IntersectionObserver::create(const IntersectionObserverIni
t& observerInit, IntersectionObserverCallback& callback, ExceptionState& excepti
onState) | 82 IntersectionObserver* IntersectionObserver::create(const IntersectionObserverIni
t& observerInit, IntersectionObserverCallback& callback, ExceptionState& excepti
onState) |
| 83 { | 83 { |
| 84 RefPtrWillBeRawPtr<Element> root = observerInit.root(); | 84 RefPtrWillBeRawPtr<Node> root = observerInit.root(); |
| 85 if (!root) { | 85 if (!root) { |
| 86 // TODO(szager): Use Document instead of document element for implicit r
oot. (crbug.com/570538) | 86 // TODO(szager): Use Document instead of document element for implicit r
oot. (crbug.com/570538) |
| 87 ExecutionContext* context = callback.executionContext(); | 87 ExecutionContext* context = callback.executionContext(); |
| 88 ASSERT(context->isDocument()); | 88 ASSERT(context->isDocument()); |
| 89 Frame* mainFrame = toDocument(context)->frame()->tree().top(); | 89 Frame* mainFrame = toDocument(context)->frame()->tree().top(); |
| 90 if (mainFrame && mainFrame->isLocalFrame()) | 90 if (mainFrame && mainFrame->isLocalFrame()) |
| 91 root = toLocalFrame(mainFrame)->document()->documentElement(); | 91 root = toLocalFrame(mainFrame)->document(); |
| 92 } | 92 } |
| 93 if (!root) { | 93 if (!root) { |
| 94 exceptionState.throwDOMException(HierarchyRequestError, "Unable to get r
oot element in main frame to track."); | 94 exceptionState.throwDOMException(HierarchyRequestError, "Unable to get r
oot node in main frame to track."); |
| 95 return nullptr; | 95 return nullptr; |
| 96 } | 96 } |
| 97 | 97 |
| 98 Vector<Length> rootMargin; | 98 Vector<Length> rootMargin; |
| 99 if (observerInit.hasRootMargin()) | 99 if (observerInit.hasRootMargin()) |
| 100 parseRootMargin(observerInit.rootMargin(), rootMargin, exceptionState); | 100 parseRootMargin(observerInit.rootMargin(), rootMargin, exceptionState); |
| 101 if (exceptionState.hadException()) | 101 if (exceptionState.hadException()) |
| 102 return nullptr; | 102 return nullptr; |
| 103 | 103 |
| 104 Vector<float> thresholds; | 104 Vector<float> thresholds; |
| 105 if (observerInit.hasThreshold()) | 105 if (observerInit.hasThreshold()) |
| 106 parseThresholds(observerInit.threshold(), thresholds, exceptionState); | 106 parseThresholds(observerInit.threshold(), thresholds, exceptionState); |
| 107 else | 107 else |
| 108 thresholds.append(0); | 108 thresholds.append(0); |
| 109 if (exceptionState.hadException()) | 109 if (exceptionState.hadException()) |
| 110 return nullptr; | 110 return nullptr; |
| 111 | 111 |
| 112 return new IntersectionObserver(callback, *root, rootMargin, thresholds); | 112 return new IntersectionObserver(callback, *root, rootMargin, thresholds); |
| 113 } | 113 } |
| 114 | 114 |
| 115 IntersectionObserver::IntersectionObserver(IntersectionObserverCallback& callbac
k, Element& root, const Vector<Length>& rootMargin, const Vector<float>& thresho
lds) | 115 IntersectionObserver::IntersectionObserver(IntersectionObserverCallback& callbac
k, Node& root, const Vector<Length>& rootMargin, const Vector<float>& thresholds
) |
| 116 : m_callback(&callback) | 116 : m_callback(&callback) |
| 117 , m_root(root.ensureIntersectionObserverData().createWeakPtr(&root)) | |
| 118 , m_thresholds(thresholds) | 117 , m_thresholds(thresholds) |
| 119 , m_topMargin(Fixed) | 118 , m_topMargin(Fixed) |
| 120 , m_rightMargin(Fixed) | 119 , m_rightMargin(Fixed) |
| 121 , m_bottomMargin(Fixed) | 120 , m_bottomMargin(Fixed) |
| 122 , m_leftMargin(Fixed) | 121 , m_leftMargin(Fixed) |
| 123 { | 122 { |
| 123 if (root.isDocumentNode()) |
| 124 m_root = toDocument(root).ensureIntersectionObserverData().createWeakPtr
(&root); |
| 125 else |
| 126 m_root = toElement(root).ensureIntersectionObserverData().createWeakPtr(
&root); |
| 124 switch (rootMargin.size()) { | 127 switch (rootMargin.size()) { |
| 125 case 0: | 128 case 0: |
| 126 break; | 129 break; |
| 127 case 1: | 130 case 1: |
| 128 m_topMargin = m_rightMargin = m_bottomMargin = m_leftMargin = rootMargin
[0]; | 131 m_topMargin = m_rightMargin = m_bottomMargin = m_leftMargin = rootMargin
[0]; |
| 129 break; | 132 break; |
| 130 case 2: | 133 case 2: |
| 131 m_topMargin = m_bottomMargin = rootMargin[0]; | 134 m_topMargin = m_bottomMargin = rootMargin[0]; |
| 132 m_rightMargin = m_leftMargin = rootMargin[1]; | 135 m_rightMargin = m_leftMargin = rootMargin[1]; |
| 133 break; | 136 break; |
| 134 case 3: | 137 case 3: |
| 135 m_topMargin = rootMargin[0]; | 138 m_topMargin = rootMargin[0]; |
| 136 m_rightMargin = m_leftMargin = rootMargin[1]; | 139 m_rightMargin = m_leftMargin = rootMargin[1]; |
| 137 m_bottomMargin = rootMargin[2]; | 140 m_bottomMargin = rootMargin[2]; |
| 138 break; | 141 break; |
| 139 case 4: | 142 case 4: |
| 140 m_topMargin = rootMargin[0]; | 143 m_topMargin = rootMargin[0]; |
| 141 m_rightMargin = rootMargin[1]; | 144 m_rightMargin = rootMargin[1]; |
| 142 m_bottomMargin = rootMargin[2]; | 145 m_bottomMargin = rootMargin[2]; |
| 143 m_leftMargin = rootMargin[3]; | 146 m_leftMargin = rootMargin[3]; |
| 144 break; | 147 break; |
| 145 default: | 148 default: |
| 146 ASSERT_NOT_REACHED(); | 149 ASSERT_NOT_REACHED(); |
| 147 break; | 150 break; |
| 148 } | 151 } |
| 149 root.document().ensureIntersectionObserverController().addTrackedObserver(*t
his); | 152 root.document().ensureIntersectionObserverController().addTrackedObserver(*t
his); |
| 150 } | 153 } |
| 151 | 154 |
| 152 LayoutObject* IntersectionObserver::rootLayoutObject() | 155 LayoutObject* IntersectionObserver::rootLayoutObject() const |
| 153 { | 156 { |
| 154 Element* rootElement = root(); | 157 Node* rootNode = root(); |
| 155 if (rootElement == rootElement->document().documentElement()) | 158 if (rootNode->isDocumentNode()) |
| 156 return rootElement->document().layoutView(); | 159 return toDocument(rootNode)->layoutView(); |
| 157 return rootElement->layoutObject(); | 160 return toElement(rootNode)->layoutObject(); |
| 158 } | 161 } |
| 159 | 162 |
| 160 bool IntersectionObserver::isDescendantOfRoot(const Element* target) const | 163 bool IntersectionObserver::isDescendantOfRoot(const Element* target) const |
| 161 { | 164 { |
| 162 // Is m_root an ancestor, through the DOM and frame trees, of target? | 165 // Is m_root an ancestor, through the DOM and frame trees, of target? |
| 163 Element* rootElement = m_root.get(); | 166 Node* rootNode = root(); |
| 164 if (!rootElement || !target || target == rootElement) | 167 if (!rootNode || !target || target == rootNode) |
| 165 return false; | 168 return false; |
| 166 if (!target->inDocument() || !rootElement->inDocument()) | 169 if (!target->inDocument() || !rootNode->inDocument()) |
| 167 return false; | 170 return false; |
| 168 | 171 |
| 169 Document* rootDocument = &rootElement->document(); | 172 Document* rootDocument = &rootNode->document(); |
| 170 Document* targetDocument = &target->document(); | 173 Document* targetDocument = &target->document(); |
| 171 while (targetDocument != rootDocument) { | 174 while (targetDocument != rootDocument) { |
| 172 target = targetDocument->ownerElement(); | 175 target = targetDocument->ownerElement(); |
| 173 if (!target) | 176 if (!target) |
| 174 return false; | 177 return false; |
| 175 targetDocument = &target->document(); | 178 targetDocument = &target->document(); |
| 176 } | 179 } |
| 177 return target->isDescendantOf(rootElement); | 180 if (rootNode->isDocumentNode()) { |
| 181 ASSERT(targetDocument == rootNode); |
| 182 return true; |
| 183 } |
| 184 return target->isDescendantOf(rootNode); |
| 178 } | 185 } |
| 179 | 186 |
| 180 void IntersectionObserver::observe(Element* target, ExceptionState& exceptionSta
te) | 187 void IntersectionObserver::observe(Element* target, ExceptionState& exceptionSta
te) |
| 181 { | 188 { |
| 182 checkRootAndDetachIfNeeded(); | 189 checkRootAndDetachIfNeeded(); |
| 183 if (!m_root) { | 190 if (!m_root) { |
| 184 exceptionState.throwDOMException(HierarchyRequestError, "Invalid observe
r: root element or containing document has been deleted."); | 191 exceptionState.throwDOMException(HierarchyRequestError, "Invalid observe
r: root element or containing document has been deleted."); |
| 185 return; | 192 return; |
| 186 } | 193 } |
| 187 if (!target) { | 194 if (!target) { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 | 343 |
| 337 DEFINE_TRACE(IntersectionObserver) | 344 DEFINE_TRACE(IntersectionObserver) |
| 338 { | 345 { |
| 339 visitor->trace(m_callback); | 346 visitor->trace(m_callback); |
| 340 visitor->trace(m_root); | 347 visitor->trace(m_root); |
| 341 visitor->trace(m_observations); | 348 visitor->trace(m_observations); |
| 342 visitor->trace(m_entries); | 349 visitor->trace(m_entries); |
| 343 } | 350 } |
| 344 | 351 |
| 345 } // namespace blink | 352 } // namespace blink |
| OLD | NEW |