Chromium Code Reviews| 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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, ExceptionState& exceptionSta te) |
| 176 { | 176 { |
| 177 if (!m_root) { | 177 if (!m_root) { |
| 178 exceptionState.throwDOMException(HierarchyRequestError, "Invalid observe r: root element or containing document has been deleted."); | 178 exceptionState.throwDOMException(InvalidStateError, "Invalid observer: r oot element or containing document has been deleted."); |
|
ojan
2016/02/27 01:45:45
I thought we decided this case wouldn't throw?
szager1
2016/02/29 22:35:53
Initially, I had thought this method would still t
| |
| 179 return; | 179 return; |
| 180 } | 180 } |
| 181 if (!target) { | 181 if (!target) { |
| 182 exceptionState.throwTypeError("Observation target must be an element."); | 182 exceptionState.throwTypeError("Observation target must be an element."); |
| 183 return; | 183 return; |
| 184 } | 184 } |
| 185 if (m_root.get() == target) { | 185 if (m_root.get() == target) { |
| 186 exceptionState.throwDOMException(HierarchyRequestError, "Cannot use the same element for root and target."); | 186 exceptionState.throwDOMException(HierarchyRequestError, "Cannot use the same element for root and target."); |
| 187 return; | 187 return; |
| 188 } | 188 } |
| 189 | 189 |
| 190 // TODO(szager): Add a pointer to the spec that describes this policy. | 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()); | 191 bool shouldReportRootBounds = target->document().frame()->securityContext()- >securityOrigin()->canAccess(rootNode()->document().frame()->securityContext()-> securityOrigin()); |
| 192 if (!shouldReportRootBounds && hasPercentMargin()) { | 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."); | 193 exceptionState.throwDOMException(HierarchyRequestError, "Cannot observe a cross-origin target because the observer has a root margin value specified as a percent."); |
| 194 return; | 194 return; |
| 195 } | 195 } |
| 196 | 196 |
| 197 if (target->ensureIntersectionObserverData().getObservationFor(*this)) | 197 if (target->ensureIntersectionObserverData().getObservationFor(*this)) |
| 198 return; | 198 return; |
| 199 | 199 |
| 200 IntersectionObservation* observation = new IntersectionObservation(*this, *t arget, shouldReportRootBounds); | 200 IntersectionObservation* observation = new IntersectionObservation(*this, *t arget, shouldReportRootBounds); |
| 201 target->ensureIntersectionObserverData().addObservation(*observation); | 201 target->ensureIntersectionObserverData().addObservation(*observation); |
| 202 m_observations.add(observation); | 202 m_observations.add(observation); |
| 203 } | 203 } |
| 204 | 204 |
| 205 void IntersectionObserver::unobserve(Element* target, ExceptionState&) | 205 void IntersectionObserver::unobserve(Element* target) |
| 206 { | 206 { |
| 207 if (!target || !target->intersectionObserverData()) | 207 if (!target || !target->intersectionObserverData()) |
| 208 return; | 208 return; |
| 209 // TODO(szager): unobserve callback | 209 // TODO(szager): unobserve callback |
| 210 if (IntersectionObservation* observation = target->intersectionObserverData( )->getObservationFor(*this)) | 210 if (IntersectionObservation* observation = target->intersectionObserverData( )->getObservationFor(*this)) |
| 211 observation->disconnect(); | 211 observation->disconnect(); |
| 212 } | 212 } |
| 213 | 213 |
| 214 void IntersectionObserver::computeIntersectionObservations() | 214 void IntersectionObserver::computeIntersectionObservations() |
| 215 { | 215 { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 241 HeapVector<Member<IntersectionObserverEntry>> IntersectionObserver::takeRecords( ) | 241 HeapVector<Member<IntersectionObserverEntry>> IntersectionObserver::takeRecords( ) |
| 242 { | 242 { |
| 243 HeapVector<Member<IntersectionObserverEntry>> entries; | 243 HeapVector<Member<IntersectionObserverEntry>> entries; |
| 244 entries.swap(m_entries); | 244 entries.swap(m_entries); |
| 245 return entries; | 245 return entries; |
| 246 } | 246 } |
| 247 | 247 |
| 248 Element* IntersectionObserver::root() const | 248 Element* IntersectionObserver::root() const |
| 249 { | 249 { |
| 250 Node* node = rootNode(); | 250 Node* node = rootNode(); |
| 251 if (node->isDocumentNode()) | 251 if (node && !node->isDocumentNode()) |
| 252 return nullptr; | 252 return toElement(node); |
| 253 return toElement(node); | 253 return nullptr; |
| 254 } | 254 } |
| 255 | 255 |
| 256 static void appendLength(StringBuilder& stringBuilder, const Length& length) | 256 static void appendLength(StringBuilder& stringBuilder, const Length& length) |
| 257 { | 257 { |
| 258 stringBuilder.appendNumber(length.intValue()); | 258 stringBuilder.appendNumber(length.intValue()); |
| 259 if (length.type() == Percent) | 259 if (length.type() == Percent) |
| 260 stringBuilder.append('%'); | 260 stringBuilder.append('%'); |
| 261 else | 261 else |
| 262 stringBuilder.append("px", 2); | 262 stringBuilder.append("px", 2); |
| 263 } | 263 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 342 { | 342 { |
| 343 #if ENABLE(OILPAN) | 343 #if ENABLE(OILPAN) |
| 344 visitor->template registerWeakMembers<IntersectionObserver, &IntersectionObs erver::clearWeakMembers>(this); | 344 visitor->template registerWeakMembers<IntersectionObserver, &IntersectionObs erver::clearWeakMembers>(this); |
| 345 #endif | 345 #endif |
| 346 visitor->trace(m_callback); | 346 visitor->trace(m_callback); |
| 347 visitor->trace(m_observations); | 347 visitor->trace(m_observations); |
| 348 visitor->trace(m_entries); | 348 visitor->trace(m_entries); |
| 349 } | 349 } |
| 350 | 350 |
| 351 } // namespace blink | 351 } // namespace blink |
| OLD | NEW |