void DOMSelection::addRange(Range* newRange) { if (!m_frame) return; // FIXME: Should we throw DOMException for error cases below? if (!newRange) { addConsoleError("The given range is null."); return; } if (!newRange->startContainer()) { addConsoleError("The given range has no container. Perhaps 'detach()' has been invoked on it?"); return; } FrameSelection& selection = m_frame->selection(); if (selection.isNone()) { selection.setSelectedRange(newRange, VP_DEFAULT_AFFINITY); return; } RefPtrWillBeRawPtr<Range> originalRange = selection.firstRange(); if (originalRange->startContainer()->document() != newRange->startContainer()->document()) { addConsoleError("The given range does not belong to the current selection's document."); return; } if (originalRange->startContainer()->treeScope() != newRange->startContainer()->treeScope()) { addConsoleError("The given range and the current selection belong to two different document fragments."); return; } if (originalRange->compareBoundaryPoints(Range::START_TO_END, newRange, ASSERT_NO_EXCEPTION) < 0 || newRange->compareBoundaryPoints(Range::START_TO_END, originalRange.get(), ASSERT_NO_EXCEPTION) < 0) { addConsoleError("Discontiguous selection is not supported."); return; } // FIXME: "Merge the ranges if they intersect" is Blink-specific behavior; other browsers supporting discontiguous // selection (obviously) keep each Range added and return it in getRangeAt(). But it's unclear if we can really // do the same, since we don't support discontiguous selection. Further discussions at // <https://code.google.com/p/chromium/issues/detail?id=353069>. Range* start = originalRange->compareBoundaryPoints(Range::START_TO_START, newRange, ASSERT_NO_EXCEPTION) < 0 ? originalRange.get() : newRange; Range* end = originalRange->compareBoundaryPoints(Range::END_TO_END, newRange, ASSERT_NO_EXCEPTION) < 0 ? newRange : originalRange.get(); RefPtrWillBeRawPtr<Range> merged = Range::create(originalRange->startContainer()->document(), start->startContainer(), start->startOffset(), end->endContainer(), end->endOffset()); EAffinity affinity = selection.selection().affinity(); selection.setSelectedRange(merged.get(), affinity); }
void DOMSelection::addRange(Range* newRange) { DCHECK(newRange); if (!isAvailable()) return; if (newRange->ownerDocument() != frame()->document()) return; if (!newRange->isConnected()) { addConsoleError("The given range isn't in document."); return; } FrameSelection& selection = frame()->selection(); if (newRange->ownerDocument() != selection.document()) { // "editing/selection/selection-in-iframe-removed-crash.html" goes here. return; } // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets // needs to be audited. See http://crbug.com/590369 for more details. // In the long term, we should change FrameSelection::setSelection to take a // parameter that does not require clean layout, so that modifying selection // no longer performs synchronous layout by itself. frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets(); if (selection.isNone()) { selection.setSelectedRange(EphemeralRange(newRange), VP_DEFAULT_AFFINITY); return; } Range* originalRange = selection.firstRange(); if (originalRange->startContainer()->document() != newRange->startContainer()->document()) { addConsoleError( "The given range does not belong to the current selection's document."); return; } if (originalRange->startContainer()->treeScope() != newRange->startContainer()->treeScope()) { addConsoleError( "The given range and the current selection belong to two different " "document fragments."); return; } if (originalRange->compareBoundaryPoints(Range::kStartToEnd, newRange, ASSERT_NO_EXCEPTION) < 0 || newRange->compareBoundaryPoints(Range::kStartToEnd, originalRange, ASSERT_NO_EXCEPTION) < 0) { addConsoleError("Discontiguous selection is not supported."); return; } // FIXME: "Merge the ranges if they intersect" is Blink-specific behavior; // other browsers supporting discontiguous selection (obviously) keep each // Range added and return it in getRangeAt(). But it's unclear if we can // really do the same, since we don't support discontiguous selection. Further // discussions at // <https://code.google.com/p/chromium/issues/detail?id=353069>. Range* start = originalRange->compareBoundaryPoints( Range::kStartToStart, newRange, ASSERT_NO_EXCEPTION) < 0 ? originalRange : newRange; Range* end = originalRange->compareBoundaryPoints(Range::kEndToEnd, newRange, ASSERT_NO_EXCEPTION) < 0 ? newRange : originalRange; const EphemeralRange merged = EphemeralRange(start->startPosition(), end->endPosition()); TextAffinity affinity = selection.selection().affinity(); selection.setSelectedRange(merged, affinity); }