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