Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(717)

Unified Diff: Source/core/editing/DOMSelection.cpp

Issue 800633004: ShadowRoot's getSelection().getRangeAt(0) returns an incorrect Range object (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/editing/DOMSelection.cpp
diff --git a/Source/core/editing/DOMSelection.cpp b/Source/core/editing/DOMSelection.cpp
index 25703e256911f5e5673ad5af24a39089b115e0d4..68c179e483e99cb44546c3f902c536b73c489cd6 100644
--- a/Source/core/editing/DOMSelection.cpp
+++ b/Source/core/editing/DOMSelection.cpp
@@ -48,18 +48,6 @@
namespace blink {
-static Node* selectionShadowAncestor(LocalFrame* frame)
-{
- Node* node = frame->selection().selection().base().anchorNode();
- if (!node)
- return 0;
-
- if (!node->isInShadowTree())
- return 0;
-
- return frame->document()->ancestorInThisScope(node);
-}
-
DOMSelection::DOMSelection(const TreeScope* treeScope)
: DOMWindowProperty(treeScope->rootNode().document().frame())
, m_treeScope(treeScope)
@@ -77,6 +65,17 @@ const VisibleSelection& DOMSelection::visibleSelection() const
return m_frame->selection().selection();
}
+bool DOMSelection::isInShadowTree() const
+{
+ ASSERT(m_frame);
+ const VisibleSelection& selection = visibleSelection();
+ if (selection.start().anchorNode() && selection.start().anchorNode()->isInShadowTree()) {
+ ASSERT(selection.end().anchorNode() && selection.end().anchorNode()->isInShadowTree());
+ return true;
+ }
+ return false;
+}
+
static Position anchorPosition(const VisibleSelection& selection)
{
Position anchor = selection.isBaseFirst() ? selection.start() : selection.end();
@@ -165,9 +164,22 @@ int DOMSelection::extentOffset() const
bool DOMSelection::isCollapsed() const
{
- if (!m_frame || selectionShadowAncestor(m_frame))
+ if (!m_frame)
+ return false;
+
+ FrameSelection& selection = m_frame->selection();
yosin_UTC9 2015/01/06 08:39:37 I think |isCollapsed()| should be |return anchorNo
kojii 2015/01/07 06:53:52 Done.
+ if (selection.isNone())
return true;
- return !m_frame->selection().isRange();
+
+ if (isInShadowTree()) {
+ Position anchor = anchorPosition(selection.selection());
+ ASSERT(anchor.anchorNode() && anchor.anchorNode()->isInShadowTree());
+ Position focus = focusPosition(selection.selection());
+ ASSERT(focus.anchorNode() && focus.anchorNode()->isInShadowTree());
+ return shadowAdjustedPosition(anchor) == shadowAdjustedPosition(focus);
+ }
+
+ return !selection.isRange();
}
String DOMSelection::type() const
@@ -369,11 +381,12 @@ PassRefPtrWillBeRawPtr<Range> DOMSelection::getRangeAt(int index, ExceptionState
// If you're hitting this, you've added broken multi-range selection support
ASSERT(rangeCount() == 1);
- if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) {
- ASSERT(!shadowAncestor->isShadowRoot());
- ContainerNode* container = shadowAncestor->parentOrShadowHostNode();
- int offset = shadowAncestor->nodeIndex();
- return Range::create(shadowAncestor->document(), container, offset, container, offset);
+ Position anchor = anchorPosition(visibleSelection());
yosin_UTC9 2015/01/06 08:39:37 I think we can implement as below: if (!isShadowRo
kojii 2015/01/07 06:53:52 Done.
+ ASSERT(anchor.anchorNode());
+ if (anchor.anchorNode()->isInShadowTree()) {
+ Position focus = focusPosition(visibleSelection());
+ ASSERT(focus.anchorNode() && focus.anchorNode()->isInShadowTree());
+ return Range::create(*anchor.document(), shadowAdjustedPosition(anchor), shadowAdjustedPosition(focus));
}
return m_frame->selection().firstRange();
@@ -510,6 +523,24 @@ String DOMSelection::toString()
return emptyString();
}
+Position DOMSelection::shadowAdjustedPosition(const Position& position) const
+{
+ if (position.isNull())
+ return position;
+
+ Node* containerNode = position.containerNode();
+ Node* adjustedNode = m_treeScope->ancestorInThisScope(containerNode);
+
+ if (!adjustedNode)
+ return Position();
+
+ if (containerNode == adjustedNode)
+ return Position(containerNode, position.computeOffsetInContainerNode(), Position::PositionIsOffsetInAnchor);
+
+ ASSERT(!adjustedNode->isShadowRoot());
+ return Position(adjustedNode->parentOrShadowHostNode(), adjustedNode->nodeIndex(), Position::PositionIsOffsetInAnchor);
+}
+
Node* DOMSelection::shadowAdjustedNode(const Position& position) const
{
if (position.isNull())

Powered by Google App Engine
This is Rietveld 408576698