| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 | 72 |
| 73 std::ostream& operator<<(std::ostream& os, PositionMoveType type) { | 73 std::ostream& operator<<(std::ostream& os, PositionMoveType type) { |
| 74 static const char* const texts[] = {"CodeUnit", "BackwardDeletion", | 74 static const char* const texts[] = {"CodeUnit", "BackwardDeletion", |
| 75 "GraphemeCluster"}; | 75 "GraphemeCluster"}; |
| 76 const auto& it = std::begin(texts) + static_cast<size_t>(type); | 76 const auto& it = std::begin(texts) + static_cast<size_t>(type); |
| 77 DCHECK_GE(it, std::begin(texts)) << "Unknown PositionMoveType value"; | 77 DCHECK_GE(it, std::begin(texts)) << "Unknown PositionMoveType value"; |
| 78 DCHECK_LT(it, std::end(texts)) << "Unknown PositionMoveType value"; | 78 DCHECK_LT(it, std::end(texts)) << "Unknown PositionMoveType value"; |
| 79 return os << *it; | 79 return os << *it; |
| 80 } | 80 } |
| 81 | 81 |
| 82 bool isCheckingEditableStyleFromAX = false; |
| 83 |
| 82 } // namespace | 84 } // namespace |
| 83 | 85 |
| 86 bool* checkingEditableStyleFromAXIndicator() { |
| 87 return &isCheckingEditableStyleFromAX; |
| 88 } |
| 89 |
| 84 bool needsLayoutTreeUpdate(const Node& node) { | 90 bool needsLayoutTreeUpdate(const Node& node) { |
| 85 const Document& document = node.document(); | 91 const Document& document = node.document(); |
| 86 if (document.needsLayoutTreeUpdate()) | 92 if (document.needsLayoutTreeUpdate()) |
| 87 return true; | 93 return true; |
| 88 // TODO(yosin): We should make |document::needsLayoutTreeUpdate()| to | 94 // TODO(yosin): We should make |document::needsLayoutTreeUpdate()| to |
| 89 // check |LayoutView::needsLayout()|. | 95 // check |LayoutView::needsLayout()|. |
| 90 return document.view() && document.view()->needsLayout(); | 96 return document.view() && document.view()->needsLayout(); |
| 91 } | 97 } |
| 92 | 98 |
| 93 template <typename PositionType> | 99 template <typename PositionType> |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 int comparePositions(const PositionWithAffinity& a, | 270 int comparePositions(const PositionWithAffinity& a, |
| 265 const PositionWithAffinity& b) { | 271 const PositionWithAffinity& b) { |
| 266 return comparePositions(a.position(), b.position()); | 272 return comparePositions(a.position(), b.position()); |
| 267 } | 273 } |
| 268 | 274 |
| 269 int comparePositions(const VisiblePosition& a, const VisiblePosition& b) { | 275 int comparePositions(const VisiblePosition& a, const VisiblePosition& b) { |
| 270 return comparePositions(a.deepEquivalent(), b.deepEquivalent()); | 276 return comparePositions(a.deepEquivalent(), b.deepEquivalent()); |
| 271 } | 277 } |
| 272 | 278 |
| 273 enum EditableLevel { Editable, RichlyEditable }; | 279 enum EditableLevel { Editable, RichlyEditable }; |
| 274 static bool hasEditableLevel(const Node& node, EditableLevel editableLevel) { | 280 |
| 275 DCHECK(node.document().isActive()); | 281 // TODO(editing-dev): Eliminate the code paths entering this function with dirty |
| 276 // TODO(editing-dev): We should have this check: | 282 // style, and replace it with hasEditableLevel. See crbug.com/667575 |
| 277 // DCHECK_GE(node.document().lifecycle().state(), | 283 static bool hasEditableLevelDeprecated(const Node& node, |
| 278 // DocumentLifecycle::StyleClean); | 284 EditableLevel editableLevel) { |
| 279 if (node.isPseudoElement()) | 285 if (node.isPseudoElement()) |
| 280 return false; | 286 return false; |
| 281 | 287 |
| 282 // Ideally we'd call DCHECK(!needsStyleRecalc()) here, but | |
| 283 // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion | |
| 284 // would fire in the middle of Document::setFocusedNode(). | |
| 285 | |
| 286 for (const Node& ancestor : NodeTraversal::inclusiveAncestorsOf(node)) { | 288 for (const Node& ancestor : NodeTraversal::inclusiveAncestorsOf(node)) { |
| 287 if ((ancestor.isHTMLElement() || ancestor.isDocumentNode()) && | 289 if ((ancestor.isHTMLElement() || ancestor.isDocumentNode()) && |
| 288 ancestor.layoutObject()) { | 290 ancestor.layoutObject()) { |
| 289 switch (ancestor.layoutObject()->style()->userModify()) { | 291 switch (ancestor.layoutObject()->style()->userModify()) { |
| 290 case READ_ONLY: | 292 case READ_ONLY: |
| 291 return false; | 293 return false; |
| 292 case READ_WRITE: | 294 case READ_WRITE: |
| 293 return true; | 295 return true; |
| 294 case READ_WRITE_PLAINTEXT_ONLY: | 296 case READ_WRITE_PLAINTEXT_ONLY: |
| 295 return editableLevel != RichlyEditable; | 297 return editableLevel != RichlyEditable; |
| 296 } | 298 } |
| 297 NOTREACHED(); | 299 NOTREACHED(); |
| 298 return false; | 300 return false; |
| 299 } | 301 } |
| 300 } | 302 } |
| 301 | 303 |
| 302 return false; | 304 return false; |
| 303 } | 305 } |
| 304 | 306 |
| 307 static bool hasEditableLevel(const Node& node, EditableLevel editableLevel) { |
| 308 DCHECK(node.document().isActive()); |
| 309 DCHECK_GE(node.document().lifecycle().state(), DocumentLifecycle::StyleClean); |
| 310 return hasEditableLevelDeprecated(node, editableLevel); |
| 311 } |
| 312 |
| 313 bool canCheckEditableStyleCorrectly(const Node& node) { |
| 314 Document& document = node.document(); |
| 315 if (document.lifecycle().state() >= DocumentLifecycle::StyleClean) |
| 316 return true; |
| 317 if (isCheckingEditableStyleFromAX) { |
| 318 // See crbug.com/668590 for details. |
| 319 // Reached by: |
| 320 // fast/events/onchange-text-form-field.html |
| 321 // fast/dom/search-shadow-host-crash.html |
| 322 // editing/pasteboard/style-from-rules.html |
| 323 // editing/style/inline-style-extend-run.html |
| 324 // editing/undo/remove-css-property-and-remove-style.html |
| 325 // editing/selection/first-letter-selection-crash.html |
| 326 // editing/selection/extend-by-word-002.html |
| 327 // fast/dynamic/checkbox-selection-crash.html |
| 328 return false; |
| 329 } |
| 330 if (document.lifecycle().inDetach()) { |
| 331 // fast/text/custom-font-data-crash2.html reaches here. |
| 332 // See crbug.com/668586 for details. |
| 333 return false; |
| 334 } |
| 335 if (document.nthIndexCache()) { |
| 336 // imported/wpt/html/semantics/selectors/pseudo-classes/ |
| 337 // readwrite-readonly.html reaches here. |
| 338 // See crbug.com/668592 for details. |
| 339 return false; |
| 340 } |
| 341 return true; |
| 342 } |
| 343 |
| 305 bool hasEditableStyle(const Node& node) { | 344 bool hasEditableStyle(const Node& node) { |
| 306 // TODO(editing-dev): We shouldn't check editable style in inactive documents. | 345 // TODO(editing-dev): We shouldn't check editable style in inactive documents. |
| 307 // We should hoist this check in the call stack, replace it by a DCHECK of | 346 // We should hoist this check in the call stack, replace it by a DCHECK of |
| 308 // active document and ultimately cleanup the code paths with inactive | 347 // active document and ultimately cleanup the code paths with inactive |
| 309 // documents. See crbug.com/667681 | 348 // documents. See crbug.com/667681 |
| 310 if (!node.document().isActive()) | 349 if (!node.document().isActive()) |
| 311 return false; | 350 return false; |
| 312 | 351 |
| 352 if (!canCheckEditableStyleCorrectly(node)) |
| 353 return hasEditableLevelDeprecated(node, Editable); |
| 354 |
| 355 if (node.document().lifecycle().state() < DocumentLifecycle::StyleClean) |
| 356 node.document().updateStyleAndLayoutTree(); |
| 313 return hasEditableLevel(node, Editable); | 357 return hasEditableLevel(node, Editable); |
| 314 } | 358 } |
| 315 | 359 |
| 316 bool hasRichlyEditableStyle(const Node& node) { | 360 bool hasRichlyEditableStyle(const Node& node) { |
| 317 // TODO(editing-dev): We shouldn't check editable style in inactive documents. | 361 // TODO(editing-dev): We shouldn't check editable style in inactive documents. |
| 318 // We should hoist this check in the call stack, replace it by a DCHECK of | 362 // We should hoist this check in the call stack, replace it by a DCHECK of |
| 319 // active document and ultimately cleanup the code paths with inactive | 363 // active document and ultimately cleanup the code paths with inactive |
| 320 // documents. See crbug.com/667681 | 364 // documents. See crbug.com/667681 |
| 321 if (!node.document().isActive()) | 365 if (!node.document().isActive()) |
| 322 return false; | 366 return false; |
| 323 | 367 |
| 368 if (node.document().lifecycle().state() < DocumentLifecycle::StyleClean) |
| 369 node.document().updateStyleAndLayoutTree(); |
| 370 |
| 324 return hasEditableLevel(node, RichlyEditable); | 371 return hasEditableLevel(node, RichlyEditable); |
| 325 } | 372 } |
| 326 | 373 |
| 327 bool isRootEditableElement(const Node& node) { | 374 bool isRootEditableElement(const Node& node) { |
| 328 return hasEditableStyle(node) && node.isElementNode() && | 375 return hasEditableStyle(node) && node.isElementNode() && |
| 329 (!node.parentNode() || !hasEditableStyle(*node.parentNode()) || | 376 (!node.parentNode() || !hasEditableStyle(*node.parentNode()) || |
| 330 !node.parentNode()->isElementNode() || | 377 !node.parentNode()->isElementNode() || |
| 331 &node == node.document().body()); | 378 &node == node.document().body()); |
| 332 } | 379 } |
| 333 | 380 |
| (...skipping 1808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2142 return InputType::DeleteWordBackward; | 2189 return InputType::DeleteWordBackward; |
| 2143 if (granularity == LineBoundary) | 2190 if (granularity == LineBoundary) |
| 2144 return InputType::DeleteLineBackward; | 2191 return InputType::DeleteLineBackward; |
| 2145 return InputType::DeleteContentBackward; | 2192 return InputType::DeleteContentBackward; |
| 2146 default: | 2193 default: |
| 2147 return InputType::None; | 2194 return InputType::None; |
| 2148 } | 2195 } |
| 2149 } | 2196 } |
| 2150 | 2197 |
| 2151 } // namespace blink | 2198 } // namespace blink |
| OLD | NEW |