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/ExceptionCode.h" | 10 #include "core/dom/ExceptionCode.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 break; | 46 break; |
47 case DimensionToken: | 47 case DimensionToken: |
48 switch (token.unitType()) { | 48 switch (token.unitType()) { |
49 case CSSPrimitiveValue::UnitType::Pixels: | 49 case CSSPrimitiveValue::UnitType::Pixels: |
50 rootMargin.append(Length(static_cast<int>(floor(token.numericVal
ue())), Fixed)); | 50 rootMargin.append(Length(static_cast<int>(floor(token.numericVal
ue())), Fixed)); |
51 break; | 51 break; |
52 case CSSPrimitiveValue::UnitType::Percentage: | 52 case CSSPrimitiveValue::UnitType::Percentage: |
53 rootMargin.append(Length(token.numericValue(), Percent)); | 53 rootMargin.append(Length(token.numericValue(), Percent)); |
54 break; | 54 break; |
55 default: | 55 default: |
56 exceptionState.throwTypeError("rootMargin must be specified in p
ixels or percent."); | 56 exceptionState.throwDOMException(SyntaxError, "rootMargin must b
e specified in pixels or percent."); |
57 } | 57 } |
58 break; | 58 break; |
59 default: | 59 default: |
60 exceptionState.throwTypeError("rootMargin must be specified in pixel
s or percent."); | 60 exceptionState.throwDOMException(SyntaxError, "rootMargin must be sp
ecified in pixels or percent."); |
61 } | 61 } |
62 } | 62 } |
63 } | 63 } |
64 | 64 |
65 static void parseThresholds(const DoubleOrDoubleArray& thresholdParameter, Vecto
r<float>& thresholds, ExceptionState& exceptionState) | 65 static void parseThresholds(const DoubleOrDoubleArray& thresholdParameter, Vecto
r<float>& thresholds, ExceptionState& exceptionState) |
66 { | 66 { |
67 if (thresholdParameter.isDouble()) { | 67 if (thresholdParameter.isDouble()) { |
68 thresholds.append(static_cast<float>(thresholdParameter.getAsDouble())); | 68 thresholds.append(static_cast<float>(thresholdParameter.getAsDouble())); |
69 } else { | 69 } else { |
70 for (auto thresholdValue : thresholdParameter.getAsDoubleArray()) | 70 for (auto thresholdValue : thresholdParameter.getAsDoubleArray()) |
71 thresholds.append(static_cast<float>(thresholdValue)); | 71 thresholds.append(static_cast<float>(thresholdValue)); |
72 } | 72 } |
73 | 73 |
74 for (auto thresholdValue : thresholds) { | 74 for (auto thresholdValue : thresholds) { |
75 if (thresholdValue < 0.0 || thresholdValue > 1.0) { | 75 if (thresholdValue < 0.0 || thresholdValue > 1.0) { |
76 exceptionState.throwTypeError("Threshold values must be between 0 an
d 1"); | 76 exceptionState.throwRangeError("Threshold values must be between 0 a
nd 1"); |
77 break; | 77 break; |
78 } | 78 } |
79 } | 79 } |
80 | 80 |
81 std::sort(thresholds.begin(), thresholds.end()); | 81 std::sort(thresholds.begin(), thresholds.end()); |
82 } | 82 } |
83 | 83 |
84 IntersectionObserver* IntersectionObserver::create(const IntersectionObserverIni
t& observerInit, IntersectionObserverCallback& callback, ExceptionState& excepti
onState) | 84 IntersectionObserver* IntersectionObserver::create(const IntersectionObserverIni
t& observerInit, IntersectionObserverCallback& callback, ExceptionState& excepti
onState) |
85 { | 85 { |
86 RefPtrWillBeRawPtr<Node> root = observerInit.root(); | 86 RefPtrWillBeRawPtr<Node> root = observerInit.root(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 #endif | 165 #endif |
166 | 166 |
167 LayoutObject* IntersectionObserver::rootLayoutObject() const | 167 LayoutObject* IntersectionObserver::rootLayoutObject() const |
168 { | 168 { |
169 Node* node = rootNode(); | 169 Node* node = rootNode(); |
170 if (node->isDocumentNode()) | 170 if (node->isDocumentNode()) |
171 return toDocument(node)->layoutView(); | 171 return toDocument(node)->layoutView(); |
172 return toElement(node)->layoutObject(); | 172 return toElement(node)->layoutObject(); |
173 } | 173 } |
174 | 174 |
175 void IntersectionObserver::observe(Element* target, ExceptionState& exceptionSta
te) | 175 void IntersectionObserver::observe(Element* target) |
176 { | 176 { |
177 if (!m_root) { | 177 if (!m_root || !target || m_root.get() == target) |
178 exceptionState.throwDOMException(HierarchyRequestError, "Invalid observe
r: root element or containing document has been deleted."); | |
179 return; | 178 return; |
180 } | |
181 if (!target) { | |
182 exceptionState.throwTypeError("Observation target must be an element."); | |
183 return; | |
184 } | |
185 if (m_root.get() == target) { | |
186 exceptionState.throwDOMException(HierarchyRequestError, "Cannot use the
same element for root and target."); | |
187 return; | |
188 } | |
189 | |
190 // TODO(szager): Add a pointer to the spec that describes this policy. | |
191 bool shouldReportRootBounds = target->document().frame()->securityContext()-
>securityOrigin()->canAccess(rootNode()->document().frame()->securityContext()->
securityOrigin()); | |
192 if (!shouldReportRootBounds && hasPercentMargin()) { | |
193 exceptionState.throwDOMException(HierarchyRequestError, "Cannot observe
a cross-origin target because the observer has a root margin value specified as
a percent."); | |
194 return; | |
195 } | |
196 | 179 |
197 if (target->ensureIntersectionObserverData().getObservationFor(*this)) | 180 if (target->ensureIntersectionObserverData().getObservationFor(*this)) |
198 return; | 181 return; |
199 | 182 |
| 183 bool shouldReportRootBounds = target->document().frame()->securityContext()-
>securityOrigin()->canAccess(rootNode()->document().frame()->securityContext()->
securityOrigin()); |
200 IntersectionObservation* observation = new IntersectionObservation(*this, *t
arget, shouldReportRootBounds); | 184 IntersectionObservation* observation = new IntersectionObservation(*this, *t
arget, shouldReportRootBounds); |
201 target->ensureIntersectionObserverData().addObservation(*observation); | 185 target->ensureIntersectionObserverData().addObservation(*observation); |
202 m_observations.add(observation); | 186 m_observations.add(observation); |
203 } | 187 } |
204 | 188 |
205 void IntersectionObserver::unobserve(Element* target, ExceptionState&) | 189 void IntersectionObserver::unobserve(Element* target) |
206 { | 190 { |
207 if (!target || !target->intersectionObserverData()) | 191 if (!target || !target->intersectionObserverData()) |
208 return; | 192 return; |
209 // TODO(szager): unobserve callback | 193 // TODO(szager): unobserve callback |
210 if (IntersectionObservation* observation = target->intersectionObserverData(
)->getObservationFor(*this)) | 194 if (IntersectionObservation* observation = target->intersectionObserverData(
)->getObservationFor(*this)) |
211 observation->disconnect(); | 195 observation->disconnect(); |
212 } | 196 } |
213 | 197 |
214 void IntersectionObserver::computeIntersectionObservations() | 198 void IntersectionObserver::computeIntersectionObservations() |
215 { | 199 { |
(...skipping 25 matching lines...) Expand all Loading... |
241 HeapVector<Member<IntersectionObserverEntry>> IntersectionObserver::takeRecords(
) | 225 HeapVector<Member<IntersectionObserverEntry>> IntersectionObserver::takeRecords(
) |
242 { | 226 { |
243 HeapVector<Member<IntersectionObserverEntry>> entries; | 227 HeapVector<Member<IntersectionObserverEntry>> entries; |
244 entries.swap(m_entries); | 228 entries.swap(m_entries); |
245 return entries; | 229 return entries; |
246 } | 230 } |
247 | 231 |
248 Element* IntersectionObserver::root() const | 232 Element* IntersectionObserver::root() const |
249 { | 233 { |
250 Node* node = rootNode(); | 234 Node* node = rootNode(); |
251 if (node->isDocumentNode()) | 235 if (node && !node->isDocumentNode()) |
252 return nullptr; | 236 return toElement(node); |
253 return toElement(node); | 237 return nullptr; |
254 } | 238 } |
255 | 239 |
256 static void appendLength(StringBuilder& stringBuilder, const Length& length) | 240 static void appendLength(StringBuilder& stringBuilder, const Length& length) |
257 { | 241 { |
258 stringBuilder.appendNumber(length.intValue()); | 242 stringBuilder.appendNumber(length.intValue()); |
259 if (length.type() == Percent) | 243 if (length.type() == Percent) |
260 stringBuilder.append('%'); | 244 stringBuilder.append('%'); |
261 else | 245 else |
262 stringBuilder.append("px", 2); | 246 stringBuilder.append("px", 2); |
263 } | 247 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 { | 307 { |
324 | 308 |
325 if (m_entries.isEmpty()) | 309 if (m_entries.isEmpty()) |
326 return; | 310 return; |
327 | 311 |
328 HeapVector<Member<IntersectionObserverEntry>> entries; | 312 HeapVector<Member<IntersectionObserverEntry>> entries; |
329 entries.swap(m_entries); | 313 entries.swap(m_entries); |
330 m_callback->handleEvent(entries, *this); | 314 m_callback->handleEvent(entries, *this); |
331 } | 315 } |
332 | 316 |
333 bool IntersectionObserver::hasPercentMargin() const | |
334 { | |
335 return (m_topMargin.type() == Percent | |
336 || m_rightMargin.type() == Percent | |
337 || m_bottomMargin.type() == Percent | |
338 || m_leftMargin.type() == Percent); | |
339 } | |
340 | |
341 DEFINE_TRACE(IntersectionObserver) | 317 DEFINE_TRACE(IntersectionObserver) |
342 { | 318 { |
343 #if ENABLE(OILPAN) | 319 #if ENABLE(OILPAN) |
344 visitor->template registerWeakMembers<IntersectionObserver, &IntersectionObs
erver::clearWeakMembers>(this); | 320 visitor->template registerWeakMembers<IntersectionObserver, &IntersectionObs
erver::clearWeakMembers>(this); |
345 #endif | 321 #endif |
346 visitor->trace(m_callback); | 322 visitor->trace(m_callback); |
347 visitor->trace(m_observations); | 323 visitor->trace(m_observations); |
348 visitor->trace(m_entries); | 324 visitor->trace(m_entries); |
349 } | 325 } |
350 | 326 |
351 } // namespace blink | 327 } // namespace blink |
OLD | NEW |