dc50b6c223e803cc5a621dab14d53d7f36021902
[WebKit-https.git] / Source / WebCore / editing / Editor.cpp
1 /*
2  * Copyright (C) 2006-2016 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "Editor.h"
29
30 #include "AXObjectCache.h"
31 #include "AlternativeTextController.h"
32 #include "ApplyStyleCommand.h"
33 #include "CSSComputedStyleDeclaration.h"
34 #include "CSSPropertyNames.h"
35 #include "CSSValueList.h"
36 #include "CSSValuePool.h"
37 #include "CachedResourceLoader.h"
38 #include "ChangeListTypeCommand.h"
39 #include "ClipboardEvent.h"
40 #include "CompositionEvent.h"
41 #include "CreateLinkCommand.h"
42 #include "CustomUndoStep.h"
43 #include "DataTransfer.h"
44 #include "DeleteSelectionCommand.h"
45 #include "DictationAlternative.h"
46 #include "DictationCommand.h"
47 #include "DocumentFragment.h"
48 #include "DocumentMarkerController.h"
49 #include "Editing.h"
50 #include "EditorClient.h"
51 #include "EventHandler.h"
52 #include "EventNames.h"
53 #include "File.h"
54 #include "FocusController.h"
55 #include "FontAttributes.h"
56 #include "Frame.h"
57 #include "FrameLoader.h"
58 #include "FrameTree.h"
59 #include "FrameView.h"
60 #include "GraphicsContext.h"
61 #include "HTMLAttachmentElement.h"
62 #include "HTMLBRElement.h"
63 #include "HTMLCollection.h"
64 #include "HTMLFormControlElement.h"
65 #include "HTMLFrameOwnerElement.h"
66 #include "HTMLImageElement.h"
67 #include "HTMLInputElement.h"
68 #include "HTMLNames.h"
69 #include "HTMLOListElement.h"
70 #include "HTMLQuoteElement.h"
71 #include "HTMLSpanElement.h"
72 #include "HTMLUListElement.h"
73 #include "HitTestResult.h"
74 #include "IndentOutdentCommand.h"
75 #include "InputEvent.h"
76 #include "InsertEditableImageCommand.h"
77 #include "InsertListCommand.h"
78 #include "InsertTextCommand.h"
79 #include "KeyboardEvent.h"
80 #include "Logging.h"
81 #include "ModifySelectionListLevel.h"
82 #include "NodeList.h"
83 #include "NodeTraversal.h"
84 #include "Page.h"
85 #include "Pasteboard.h"
86 #include "Range.h"
87 #include "RemoveFormatCommand.h"
88 #include "RenderBlock.h"
89 #include "RenderTextControl.h"
90 #include "RenderedDocumentMarker.h"
91 #include "RenderedPosition.h"
92 #include "ReplaceRangeWithTextCommand.h"
93 #include "ReplaceSelectionCommand.h"
94 #include "RuntimeEnabledFeatures.h"
95 #include "SerializedAttachmentData.h"
96 #include "Settings.h"
97 #include "ShadowRoot.h"
98 #include "SharedBuffer.h"
99 #include "SimplifyMarkupCommand.h"
100 #include "SpellChecker.h"
101 #include "SpellingCorrectionCommand.h"
102 #include "StaticPasteboard.h"
103 #include "StyleProperties.h"
104 #include "TelephoneNumberDetector.h"
105 #include "Text.h"
106 #include "TextCheckerClient.h"
107 #include "TextCheckingHelper.h"
108 #include "TextEvent.h"
109 #include "TextIterator.h"
110 #include "TypingCommand.h"
111 #include "UserTypingGestureIndicator.h"
112 #include "VisibleUnits.h"
113 #include "markup.h"
114 #include <pal/FileSizeFormatter.h>
115 #include <pal/system/Sound.h>
116 #include <pal/text/KillRing.h>
117 #include <wtf/unicode/CharacterNames.h>
118
119 #if PLATFORM(MAC)
120 #include "ServicesOverlayController.h"
121 #endif
122
123 namespace WebCore {
124
125 static bool dispatchBeforeInputEvent(Element& element, const AtomicString& inputType, const String& data = { }, RefPtr<DataTransfer>&& dataTransfer = nullptr, const Vector<RefPtr<StaticRange>>& targetRanges = { }, Event::IsCancelable cancelable = Event::IsCancelable::Yes)
126 {
127     if (!element.document().settings().inputEventsEnabled())
128         return true;
129
130     auto event = InputEvent::create(eventNames().beforeinputEvent, inputType, cancelable, element.document().windowProxy(), data, WTFMove(dataTransfer), targetRanges, 0);
131     element.dispatchEvent(event);
132     return !event->defaultPrevented();
133 }
134
135 static void dispatchInputEvent(Element& element, const AtomicString& inputType, const String& data = { }, RefPtr<DataTransfer>&& dataTransfer = nullptr, const Vector<RefPtr<StaticRange>>& targetRanges = { })
136 {
137     if (element.document().settings().inputEventsEnabled()) {
138         // FIXME: We should not be dispatching to the scoped queue here. Normally, input events are dispatched in CompositeEditCommand::apply after the end of the scope,
139         // but TypingCommands are special in that existing TypingCommands that are applied again fire input events *from within* the scope by calling typingAddedToOpenCommand.
140         // Instead, TypingCommands should always dispatch events synchronously after the end of the scoped queue in CompositeEditCommand::apply. To work around this for the
141         // time being, just revert back to calling dispatchScopedEvent.
142         element.dispatchScopedEvent(InputEvent::create(eventNames().inputEvent, inputType, Event::IsCancelable::No,
143             element.document().windowProxy(), data, WTFMove(dataTransfer), targetRanges, 0));
144     } else
145         element.dispatchInputEvent();
146 }
147
148 static String inputEventDataForEditingStyleAndAction(const StyleProperties* style, EditAction action)
149 {
150     if (!style)
151         return { };
152
153     switch (action) {
154     case EditAction::SetColor:
155         return style->getPropertyValue(CSSPropertyColor);
156     case EditAction::SetInlineWritingDirection:
157     case EditAction::SetBlockWritingDirection:
158         return style->getPropertyValue(CSSPropertyDirection);
159     default:
160         return { };
161     }
162 }
163
164 static String inputEventDataForEditingStyleAndAction(EditingStyle& style, EditAction action)
165 {
166     return inputEventDataForEditingStyleAndAction(style.style(), action);
167 }
168
169 class ClearTextCommand : public DeleteSelectionCommand {
170 public:
171     ClearTextCommand(Document& document);
172     static void CreateAndApply(const RefPtr<Frame> frame);
173     
174 private:
175     EditAction editingAction() const override;
176 };
177
178 ClearTextCommand::ClearTextCommand(Document& document)
179     : DeleteSelectionCommand(document, false, true, false, false, true)
180 {
181 }
182
183 EditAction ClearTextCommand::editingAction() const
184 {
185     return EditAction::Delete;
186 }
187
188 void ClearTextCommand::CreateAndApply(const RefPtr<Frame> frame)
189 {
190     if (frame->selection().isNone())
191         return;
192
193     // Don't leave around stale composition state.
194     frame->editor().clear();
195     
196     const VisibleSelection oldSelection = frame->selection().selection();
197     frame->selection().selectAll();
198     auto clearCommand = adoptRef(*new ClearTextCommand(*frame->document()));
199     clearCommand->setStartingSelection(oldSelection);
200     clearCommand->apply();
201 }
202
203 using namespace HTMLNames;
204 using namespace WTF::Unicode;
205
206 TemporarySelectionChange::TemporarySelectionChange(Frame& frame, Optional<VisibleSelection> temporarySelection, OptionSet<TemporarySelectionOption> options)
207     : m_frame(frame)
208     , m_options(options)
209     , m_wasIgnoringSelectionChanges(frame.editor().ignoreSelectionChanges())
210 #if PLATFORM(IOS_FAMILY)
211     , m_appearanceUpdatesWereEnabled(frame.selection().isUpdateAppearanceEnabled())
212 #endif
213 {
214 #if PLATFORM(IOS_FAMILY)
215     if (options & TemporarySelectionOption::EnableAppearanceUpdates)
216         frame.selection().setUpdateAppearanceEnabled(true);
217 #endif
218
219     if (options & TemporarySelectionOption::IgnoreSelectionChanges)
220         frame.editor().setIgnoreSelectionChanges(true);
221
222     if (temporarySelection) {
223         m_selectionToRestore = frame.selection().selection();
224         setSelection(temporarySelection.value());
225     }
226 }
227
228 TemporarySelectionChange::~TemporarySelectionChange()
229 {
230     if (m_selectionToRestore)
231         setSelection(m_selectionToRestore.value());
232
233     if (m_options & TemporarySelectionOption::IgnoreSelectionChanges) {
234         auto revealSelection = m_options & TemporarySelectionOption::RevealSelection ? Editor::RevealSelection::Yes : Editor::RevealSelection::No;
235         m_frame->editor().setIgnoreSelectionChanges(m_wasIgnoringSelectionChanges, revealSelection);
236     }
237
238 #if PLATFORM(IOS_FAMILY)
239     if (m_options & TemporarySelectionOption::EnableAppearanceUpdates)
240         m_frame->selection().setUpdateAppearanceEnabled(m_appearanceUpdatesWereEnabled);
241 #endif
242 }
243
244 void TemporarySelectionChange::setSelection(const VisibleSelection& selection)
245 {
246     auto options = FrameSelection::defaultSetSelectionOptions();
247     if (m_options & TemporarySelectionOption::DoNotSetFocus)
248         options.add(FrameSelection::DoNotSetFocus);
249     m_frame->selection().setSelection(selection, options);
250 }
251
252 // When an event handler has moved the selection outside of a text control
253 // we should use the target control's selection for this editing operation.
254 VisibleSelection Editor::selectionForCommand(Event* event)
255 {
256     auto selection = m_frame.selection().selection();
257     if (!event)
258         return selection;
259     // If the target is a text control, and the current selection is outside of its shadow tree,
260     // then use the saved selection for that text control.
261     if (is<Element>(event->target()) && downcast<Element>(*event->target()).isTextField()) {
262         auto& target = downcast<HTMLTextFormControlElement>(*event->target());
263         auto start = selection.start();
264         if (start.isNull() || &target != enclosingTextFormControl(start)) {
265             if (auto range = target.selection())
266                 return { *range, DOWNSTREAM, selection.isDirectional() };
267         }
268     }
269     return selection;
270 }
271
272 // Function considers Mac editing behavior a fallback when Page or Settings is not available.
273 EditingBehavior Editor::behavior() const
274 {
275     return EditingBehavior(m_frame.settings().editingBehaviorType());
276 }
277
278 EditorClient* Editor::client() const
279 {
280     if (Page* page = m_frame.page())
281         return &page->editorClient();
282     return nullptr;
283 }
284
285 TextCheckerClient* Editor::textChecker() const
286 {
287     if (EditorClient* owner = client())
288         return owner->textChecker();
289     return 0;
290 }
291
292 void Editor::handleKeyboardEvent(KeyboardEvent& event)
293 {
294     if (auto* client = this->client())
295         client->handleKeyboardEvent(event);
296 }
297
298 void Editor::handleInputMethodKeydown(KeyboardEvent& event)
299 {
300     if (auto* client = this->client())
301         client->handleInputMethodKeydown(event);
302 }
303
304 bool Editor::handleTextEvent(TextEvent& event)
305 {
306     LOG(Editing, "Editor %p handleTextEvent (data %s)", this, event.data().utf8().data());
307
308     // Default event handling for Drag and Drop will be handled by DragController
309     // so we leave the event for it.
310     if (event.isDrop())
311         return false;
312
313     if (event.isPaste()) {
314         if (event.pastingFragment()) {
315 #if PLATFORM(IOS_FAMILY)
316             if (client()->performsTwoStepPaste(event.pastingFragment()))
317                 return true;
318 #endif
319             replaceSelectionWithFragment(*event.pastingFragment(), SelectReplacement::No, event.shouldSmartReplace() ? SmartReplace::Yes : SmartReplace::No, event.shouldMatchStyle() ? MatchStyle::Yes : MatchStyle::No, EditAction::Paste, event.mailBlockquoteHandling());
320         } else
321             replaceSelectionWithText(event.data(), SelectReplacement::No, event.shouldSmartReplace() ? SmartReplace::Yes : SmartReplace::No, EditAction::Paste);
322         return true;
323     }
324
325     String data = event.data();
326     if (data == "\n") {
327         if (event.isLineBreak())
328             return insertLineBreak();
329         return insertParagraphSeparator();
330     }
331
332     return insertTextWithoutSendingTextEvent(data, false, &event);
333 }
334
335 bool Editor::canEdit() const
336 {
337     return m_frame.selection().selection().rootEditableElement();
338 }
339
340 bool Editor::canEditRichly() const
341 {
342     return m_frame.selection().selection().isContentRichlyEditable();
343 }
344
345 enum class ClipboardEventKind {
346     Copy,
347     Cut,
348     Paste,
349     PasteAsPlainText,
350     PasteAsQuotation,
351     BeforeCopy,
352     BeforeCut,
353     BeforePaste,
354 };
355
356 static AtomicString eventNameForClipboardEvent(ClipboardEventKind kind)
357 {
358     switch (kind) {
359     case ClipboardEventKind::Copy:
360         return eventNames().copyEvent;
361     case ClipboardEventKind::Cut:
362         return eventNames().cutEvent;
363     case ClipboardEventKind::Paste:
364     case ClipboardEventKind::PasteAsPlainText:
365     case ClipboardEventKind::PasteAsQuotation:
366         return eventNames().pasteEvent;
367     case ClipboardEventKind::BeforeCopy:
368         return eventNames().beforecopyEvent;
369     case ClipboardEventKind::BeforeCut:
370         return eventNames().beforecutEvent;
371     case ClipboardEventKind::BeforePaste:
372         return eventNames().beforepasteEvent;
373     }
374     ASSERT_NOT_REACHED();
375     return { };
376 }
377
378 static Ref<DataTransfer> createDataTransferForClipboardEvent(Document& document, ClipboardEventKind kind)
379 {
380     switch (kind) {
381     case ClipboardEventKind::Copy:
382     case ClipboardEventKind::Cut:
383         return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::ReadWrite, std::make_unique<StaticPasteboard>());
384     case ClipboardEventKind::PasteAsPlainText:
385         if (RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled()) {
386             auto plainTextType = "text/plain"_s;
387             auto plainText = Pasteboard::createForCopyAndPaste()->readString(plainTextType);
388             auto pasteboard = std::make_unique<StaticPasteboard>();
389             pasteboard->writeString(plainTextType, plainText);
390             return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Readonly, WTFMove(pasteboard));
391         }
392         FALLTHROUGH;
393     case ClipboardEventKind::Paste:
394     case ClipboardEventKind::PasteAsQuotation:
395         return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Readonly, Pasteboard::createForCopyAndPaste());
396     case ClipboardEventKind::BeforeCopy:
397     case ClipboardEventKind::BeforeCut:
398     case ClipboardEventKind::BeforePaste:
399         return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Invalid, std::make_unique<StaticPasteboard>());
400     }
401     ASSERT_NOT_REACHED();
402     return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Invalid, std::make_unique<StaticPasteboard>());
403 }
404
405 // Returns whether caller should continue with "the default processing", which is the same as
406 // the event handler NOT setting the return value to false
407 // https://w3c.github.io/clipboard-apis/#fire-a-clipboard-event
408 static bool dispatchClipboardEvent(RefPtr<Element>&& target, ClipboardEventKind kind)
409 {
410     // FIXME: Move the target selection code here.
411     if (!target)
412         return true;
413
414     auto dataTransfer = createDataTransferForClipboardEvent(target->document(), kind);
415
416     auto event = ClipboardEvent::create(eventNameForClipboardEvent(kind), dataTransfer.copyRef());
417
418     target->dispatchEvent(event);
419     bool noDefaultProcessing = event->defaultPrevented();
420     if (noDefaultProcessing && (kind == ClipboardEventKind::Copy || kind == ClipboardEventKind::Cut)) {
421         auto pasteboard = Pasteboard::createForCopyAndPaste();
422         pasteboard->clear();
423         dataTransfer->commitToPasteboard(*pasteboard);
424     }
425
426     dataTransfer->makeInvalidForSecurity();
427
428     return !noDefaultProcessing;
429 }
430
431 // WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu items.  They
432 // also send onbeforecopy, apparently for symmetry, but it doesn't affect the menu items.
433 // We need to use onbeforecopy as a real menu enabler because we allow elements that are not
434 // normally selectable to implement copy/paste (like divs, or a document body).
435
436 bool Editor::canDHTMLCut()
437 {
438     if (m_frame.selection().selection().isInPasswordField())
439         return false;
440
441     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::BeforeCut);
442 }
443
444 bool Editor::canDHTMLCopy()
445 {
446     if (m_frame.selection().selection().isInPasswordField())
447         return false;
448     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::BeforeCopy);
449 }
450
451 bool Editor::canDHTMLPaste()
452 {
453     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::BeforePaste);
454 }
455
456 bool Editor::canCut() const
457 {
458     return canCopy() && canDelete();
459 }
460
461 static HTMLImageElement* imageElementFromImageDocument(Document& document)
462 {
463     if (!document.isImageDocument())
464         return nullptr;
465     
466     HTMLElement* body = document.bodyOrFrameset();
467     if (!body)
468         return nullptr;
469     
470     Node* node = body->firstChild();
471     if (!is<HTMLImageElement>(node))
472         return nullptr;
473     return downcast<HTMLImageElement>(node);
474 }
475
476 bool Editor::canCopy() const
477 {
478     if (imageElementFromImageDocument(document()))
479         return true;
480     const VisibleSelection& selection = m_frame.selection().selection();
481     return selection.isRange() && !selection.isInPasswordField();
482 }
483
484 bool Editor::canPaste() const
485 {
486     if (m_frame.mainFrame().loader().shouldSuppressTextInputFromEditing())
487         return false;
488
489     return canEdit();
490 }
491
492 bool Editor::canDelete() const
493 {
494     const VisibleSelection& selection = m_frame.selection().selection();
495     return selection.isRange() && selection.rootEditableElement();
496 }
497
498 bool Editor::canDeleteRange(Range* range) const
499 {
500     Node& startContainer = range->startContainer();
501     Node& endContainer = range->endContainer();
502     
503     if (!startContainer.hasEditableStyle() || !endContainer.hasEditableStyle())
504         return false;
505
506     if (range->collapsed()) {
507         VisiblePosition start(range->startPosition(), DOWNSTREAM);
508         VisiblePosition previous = start.previous();
509         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
510         if (previous.isNull() || previous.deepEquivalent().deprecatedNode()->rootEditableElement() != startContainer.rootEditableElement())
511             return false;
512     }
513     return true;
514 }
515
516 bool Editor::shouldSmartDelete()
517 {
518     if (behavior().shouldAlwaysSmartDelete())
519         return true;
520     return m_frame.selection().granularity() == WordGranularity;
521 }
522
523 bool Editor::smartInsertDeleteEnabled()
524 {   
525     return client() && client()->smartInsertDeleteEnabled();
526 }
527     
528 bool Editor::canSmartCopyOrDelete()
529 {
530     return client() && client()->smartInsertDeleteEnabled() && shouldSmartDelete();
531 }
532
533 bool Editor::isSelectTrailingWhitespaceEnabled() const
534 {
535     return client() && client()->isSelectTrailingWhitespaceEnabled();
536 }
537
538 bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity granularity, bool shouldAddToKillRing, bool isTypingAction)
539 {
540     if (!canEdit())
541         return false;
542
543     if (m_frame.selection().isRange()) {
544         if (isTypingAction) {
545             TypingCommand::deleteKeyPressed(document(), canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
546             revealSelectionAfterEditingOperation();
547         } else {
548             if (shouldAddToKillRing)
549                 addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
550             deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
551             // Implicitly calls revealSelectionAfterEditingOperation().
552         }
553     } else {
554         TypingCommand::Options options = 0;
555         if (canSmartCopyOrDelete())
556             options |= TypingCommand::SmartDelete;
557         if (shouldAddToKillRing)
558             options |= TypingCommand::AddsToKillRing;
559         switch (direction) {
560         case DirectionForward:
561         case DirectionRight:
562             TypingCommand::forwardDeleteKeyPressed(document(), options, granularity);
563             break;
564         case DirectionBackward:
565         case DirectionLeft:
566             TypingCommand::deleteKeyPressed(document(), options, granularity);
567             break;
568         }
569         revealSelectionAfterEditingOperation();
570     }
571
572     // FIXME: We should to move this down into deleteKeyPressed.
573     // clear the "start new kill ring sequence" setting, because it was set to true
574     // when the selection was updated by deleting the range
575     if (shouldAddToKillRing)
576         setStartNewKillRingSequence(false);
577
578     return true;
579 }
580
581 void Editor::deleteSelectionWithSmartDelete(bool smartDelete, EditAction editingAction)
582 {
583     if (m_frame.selection().isNone())
584         return;
585
586     DeleteSelectionCommand::create(document(), smartDelete, true, false, false, true, editingAction)->apply();
587 }
588
589 void Editor::clearText()
590 {
591     ClearTextCommand::CreateAndApply(&m_frame);
592 }
593
594 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace)
595 {
596     Element* target = findEventTargetFromSelection();
597     if (!target)
598         return;
599     target->dispatchEvent(TextEvent::createForPlainTextPaste(document().windowProxy(), pastingText, smartReplace));
600 }
601
602 void Editor::pasteAsFragment(Ref<DocumentFragment>&& pastingFragment, bool smartReplace, bool matchStyle, MailBlockquoteHandling respectsMailBlockquote)
603 {
604     Element* target = findEventTargetFromSelection();
605     if (!target)
606         return;
607     target->dispatchEvent(TextEvent::createForFragmentPaste(document().windowProxy(), WTFMove(pastingFragment), smartReplace, matchStyle, respectsMailBlockquote));
608 }
609
610 void Editor::pasteAsPlainTextBypassingDHTML()
611 {
612     pasteAsPlainTextWithPasteboard(*Pasteboard::createForCopyAndPaste());
613 }
614
615 void Editor::pasteAsPlainTextWithPasteboard(Pasteboard& pasteboard)
616 {
617     String text = readPlainTextFromPasteboard(pasteboard);
618     if (client() && client()->shouldInsertText(text, selectedRange().get(), EditorInsertAction::Pasted))
619         pasteAsPlainText(text, canSmartReplaceWithPasteboard(pasteboard));
620 }
621
622 String Editor::readPlainTextFromPasteboard(Pasteboard& pasteboard)
623 {
624     PasteboardPlainText text;
625     pasteboard.read(text);
626     return plainTextFromPasteboard(text);
627 }
628
629 #if !PLATFORM(MAC)
630
631 String Editor::plainTextFromPasteboard(const PasteboardPlainText& text)
632 {
633     return text.text;
634 }
635
636 #endif
637
638 bool Editor::canSmartReplaceWithPasteboard(Pasteboard& pasteboard)
639 {
640     return client() && client()->smartInsertDeleteEnabled() && pasteboard.canSmartReplace();
641 }
642
643 bool Editor::shouldInsertFragment(DocumentFragment& fragment, Range* replacingDOMRange, EditorInsertAction givenAction)
644 {
645     if (!client())
646         return false;
647     
648     auto* child = fragment.firstChild();
649     if (is<CharacterData>(child) && fragment.lastChild() == child)
650         return client()->shouldInsertText(downcast<CharacterData>(*child).data(), replacingDOMRange, givenAction);
651
652     return client()->shouldInsertNode(&fragment, replacingDOMRange, givenAction);
653 }
654
655 void Editor::replaceSelectionWithFragment(DocumentFragment& fragment, SelectReplacement selectReplacement, SmartReplace smartReplace, MatchStyle matchStyle, EditAction editingAction, MailBlockquoteHandling mailBlockquoteHandling)
656 {
657     VisibleSelection selection = m_frame.selection().selection();
658     if (selection.isNone() || !selection.isContentEditable())
659         return;
660
661     AccessibilityReplacedText replacedText;
662     if (AXObjectCache::accessibilityEnabled() && editingAction == EditAction::Paste)
663         replacedText = AccessibilityReplacedText(selection);
664
665     OptionSet<ReplaceSelectionCommand::CommandOption> options { ReplaceSelectionCommand::PreventNesting, ReplaceSelectionCommand::SanitizeFragment };
666     if (selectReplacement == SelectReplacement::Yes)
667         options.add(ReplaceSelectionCommand::SelectReplacement);
668     if (smartReplace == SmartReplace::Yes)
669         options.add(ReplaceSelectionCommand::SmartReplace);
670     if (matchStyle == MatchStyle::Yes)
671         options.add(ReplaceSelectionCommand::MatchStyle);
672     if (mailBlockquoteHandling == MailBlockquoteHandling::IgnoreBlockquote)
673         options.add(ReplaceSelectionCommand::IgnoreMailBlockquote);
674
675     auto command = ReplaceSelectionCommand::create(document(), &fragment, options, editingAction);
676     command->apply();
677     revealSelectionAfterEditingOperation();
678
679     selection = m_frame.selection().selection();
680     if (selection.isInPasswordField())
681         return;
682
683     if (AXObjectCache::accessibilityEnabled() && editingAction == EditAction::Paste) {
684         String text = AccessibilityObject::stringForVisiblePositionRange(command->visibleSelectionForInsertedText());
685         replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypePaste, text, m_frame.selection().selection());
686         command->composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
687     }
688
689     if (!isContinuousSpellCheckingEnabled())
690         return;
691
692     Node* nodeToCheck = selection.rootEditableElement();
693     if (!nodeToCheck)
694         return;
695
696     auto rangeToCheck = Range::create(document(), firstPositionInNode(nodeToCheck), lastPositionInNode(nodeToCheck));
697     if (auto request = SpellCheckRequest::create(resolveTextCheckingTypeMask(*nodeToCheck, { TextCheckingType::Spelling, TextCheckingType::Grammar }), TextCheckingProcessBatch, rangeToCheck.copyRef(), rangeToCheck.copyRef(), rangeToCheck.copyRef()))
698         m_spellChecker->requestCheckingFor(request.releaseNonNull());
699 }
700
701 void Editor::replaceSelectionWithText(const String& text, SelectReplacement selectReplacement, SmartReplace smartReplace, EditAction editingAction)
702 {
703     RefPtr<Range> range = selectedRange();
704     if (!range)
705         return;
706
707     replaceSelectionWithFragment(createFragmentFromText(*range, text), selectReplacement, smartReplace, MatchStyle::Yes, editingAction);
708 }
709
710 RefPtr<Range> Editor::selectedRange()
711 {
712     return m_frame.selection().toNormalizedRange();
713 }
714
715 bool Editor::shouldDeleteRange(Range* range) const
716 {
717     if (!range || range->collapsed())
718         return false;
719     
720     if (!canDeleteRange(range))
721         return false;
722
723     return client() && client()->shouldDeleteRange(range);
724 }
725
726 bool Editor::tryDHTMLCopy()
727 {   
728     if (m_frame.selection().selection().isInPasswordField())
729         return false;
730
731     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Copy);
732 }
733
734 bool Editor::tryDHTMLCut()
735 {
736     if (m_frame.selection().selection().isInPasswordField())
737         return false;
738     
739     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Cut);
740 }
741
742 bool Editor::shouldInsertText(const String& text, Range* range, EditorInsertAction action) const
743 {
744     if (m_frame.mainFrame().loader().shouldSuppressTextInputFromEditing() && action == EditorInsertAction::Typed)
745         return false;
746
747     return client() && client()->shouldInsertText(text, range, action);
748 }
749
750 void Editor::respondToChangedContents(const VisibleSelection& endingSelection)
751 {
752     if (AXObjectCache::accessibilityEnabled()) {
753         Node* node = endingSelection.start().deprecatedNode();
754         if (AXObjectCache* cache = document().existingAXObjectCache())
755             cache->postNotification(node, AXObjectCache::AXValueChanged, TargetObservableParent);
756     }
757
758     updateMarkersForWordsAffectedByEditing(true);
759
760     if (client())
761         client()->respondToChangedContents();
762 }
763
764 bool Editor::hasBidiSelection() const
765 {
766     if (m_frame.selection().isNone())
767         return false;
768
769     Node* startNode;
770     if (m_frame.selection().isRange()) {
771         startNode = m_frame.selection().selection().start().downstream().deprecatedNode();
772         Node* endNode = m_frame.selection().selection().end().upstream().deprecatedNode();
773         if (enclosingBlock(startNode) != enclosingBlock(endNode))
774             return false;
775     } else
776         startNode = m_frame.selection().selection().visibleStart().deepEquivalent().deprecatedNode();
777
778     if (!startNode)
779         return false;
780
781     auto renderer = startNode->renderer();
782     while (renderer && !is<RenderBlockFlow>(*renderer))
783         renderer = renderer->parent();
784
785     if (!renderer)
786         return false;
787
788     if (!renderer->style().isLeftToRightDirection())
789         return true;
790
791     return downcast<RenderBlockFlow>(*renderer).containsNonZeroBidiLevel();
792 }
793
794 TriState Editor::selectionUnorderedListState() const
795 {
796     if (m_frame.selection().isCaret()) {
797         if (enclosingElementWithTag(m_frame.selection().selection().start(), ulTag))
798             return TrueTriState;
799     } else if (m_frame.selection().isRange()) {
800         auto* startNode = enclosingElementWithTag(m_frame.selection().selection().start(), ulTag);
801         auto* endNode = enclosingElementWithTag(m_frame.selection().selection().end(), ulTag);
802         if (startNode && endNode && startNode == endNode)
803             return TrueTriState;
804     }
805
806     return FalseTriState;
807 }
808
809 TriState Editor::selectionOrderedListState() const
810 {
811     if (m_frame.selection().isCaret()) {
812         if (enclosingElementWithTag(m_frame.selection().selection().start(), olTag))
813             return TrueTriState;
814     } else if (m_frame.selection().isRange()) {
815         auto* startNode = enclosingElementWithTag(m_frame.selection().selection().start(), olTag);
816         auto* endNode = enclosingElementWithTag(m_frame.selection().selection().end(), olTag);
817         if (startNode && endNode && startNode == endNode)
818             return TrueTriState;
819     }
820
821     return FalseTriState;
822 }
823
824 RefPtr<Node> Editor::insertOrderedList()
825 {
826     if (!canEditRichly())
827         return nullptr;
828         
829     auto newList = InsertListCommand::insertList(document(), InsertListCommand::Type::OrderedList);
830     revealSelectionAfterEditingOperation();
831     return newList;
832 }
833
834 RefPtr<Node> Editor::insertUnorderedList()
835 {
836     if (!canEditRichly())
837         return nullptr;
838         
839     auto newList = InsertListCommand::insertList(document(), InsertListCommand::Type::UnorderedList);
840     revealSelectionAfterEditingOperation();
841     return newList;
842 }
843
844 bool Editor::canIncreaseSelectionListLevel()
845 {
846     return canEditRichly() && IncreaseSelectionListLevelCommand::canIncreaseSelectionListLevel(&document());
847 }
848
849 bool Editor::canDecreaseSelectionListLevel()
850 {
851     return canEditRichly() && DecreaseSelectionListLevelCommand::canDecreaseSelectionListLevel(&document());
852 }
853
854 RefPtr<Node> Editor::increaseSelectionListLevel()
855 {
856     if (!canEditRichly() || m_frame.selection().isNone())
857         return nullptr;
858     
859     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevel(&document());
860     revealSelectionAfterEditingOperation();
861     return newList;
862 }
863
864 RefPtr<Node> Editor::increaseSelectionListLevelOrdered()
865 {
866     if (!canEditRichly() || m_frame.selection().isNone())
867         return nullptr;
868     
869     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(&document());
870     revealSelectionAfterEditingOperation();
871     return newList;
872 }
873
874 RefPtr<Node> Editor::increaseSelectionListLevelUnordered()
875 {
876     if (!canEditRichly() || m_frame.selection().isNone())
877         return nullptr;
878     
879     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(&document());
880     revealSelectionAfterEditingOperation();
881     return newList;
882 }
883
884 void Editor::decreaseSelectionListLevel()
885 {
886     if (!canEditRichly() || m_frame.selection().isNone())
887         return;
888     
889     DecreaseSelectionListLevelCommand::decreaseSelectionListLevel(&document());
890     revealSelectionAfterEditingOperation();
891 }
892
893 void Editor::removeFormattingAndStyle()
894 {
895     RemoveFormatCommand::create(document())->apply();
896 }
897
898 void Editor::clearLastEditCommand() 
899 {
900     m_lastEditCommand = nullptr;
901 }
902
903 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const
904 {
905     Element* target = selection.start().element();
906     if (!target)
907         target = document().bodyOrFrameset();
908     if (!target)
909         return nullptr;
910
911     return target;
912 }
913
914 Element* Editor::findEventTargetFromSelection() const
915 {
916     return findEventTargetFrom(m_frame.selection().selection());
917 }
918
919 void Editor::applyStyle(StyleProperties* style, EditAction editingAction)
920 {
921     if (style)
922         applyStyle(EditingStyle::create(style), editingAction, ColorFilterMode::UseOriginalColor);
923 }
924
925 void Editor::applyStyle(RefPtr<EditingStyle>&& style, EditAction editingAction, ColorFilterMode colorFilterMode)
926 {
927     if (!style)
928         return;
929
930     auto selectionType = m_frame.selection().selection().selectionType();
931     if (selectionType == VisibleSelection::NoSelection)
932         return;
933
934     String inputTypeName = inputTypeNameForEditingAction(editingAction);
935     String inputEventData = inputEventDataForEditingStyleAndAction(*style, editingAction);
936     RefPtr<Element> element = m_frame.selection().selection().rootEditableElement();
937     if (element && !dispatchBeforeInputEvent(*element, inputTypeName, inputEventData))
938         return;
939
940     Ref<EditingStyle> styleToApply = colorFilterMode == ColorFilterMode::InvertColor ? style->inverseTransformColorIfNeeded(*element) : style.releaseNonNull();
941
942     switch (selectionType) {
943     case VisibleSelection::CaretSelection:
944         computeAndSetTypingStyle(styleToApply.get(), editingAction);
945         break;
946     case VisibleSelection::RangeSelection:
947         ApplyStyleCommand::create(document(), styleToApply.ptr(), editingAction)->apply();
948         break;
949     default:
950         break;
951     }
952
953     client()->didApplyStyle();
954     if (element)
955         dispatchInputEvent(*element, inputTypeName, inputEventData);
956 }
957     
958 bool Editor::shouldApplyStyle(StyleProperties* style, Range* range)
959 {   
960     return client()->shouldApplyStyle(style, range);
961 }
962     
963 void Editor::applyParagraphStyle(StyleProperties* style, EditAction editingAction)
964 {
965     if (!style)
966         return;
967
968     auto selectionType = m_frame.selection().selection().selectionType();
969     if (selectionType == VisibleSelection::NoSelection)
970         return;
971
972     String inputTypeName = inputTypeNameForEditingAction(editingAction);
973     String inputEventData = inputEventDataForEditingStyleAndAction(style, editingAction);
974     RefPtr<Element> element = m_frame.selection().selection().rootEditableElement();
975     if (element && !dispatchBeforeInputEvent(*element, inputTypeName, inputEventData))
976         return;
977
978     ApplyStyleCommand::create(document(), EditingStyle::create(style).ptr(), editingAction, ApplyStyleCommand::ForceBlockProperties)->apply();
979     client()->didApplyStyle();
980     if (element)
981         dispatchInputEvent(*element, inputTypeName, inputEventData);
982 }
983
984 void Editor::applyStyleToSelection(StyleProperties* style, EditAction editingAction)
985 {
986     if (!style || style->isEmpty() || !canEditRichly())
987         return;
988
989     if (!client() || !client()->shouldApplyStyle(style, m_frame.selection().toNormalizedRange().get()))
990         return;
991     applyStyle(style, editingAction);
992 }
993
994 void Editor::applyStyleToSelection(Ref<EditingStyle>&& style, EditAction editingAction, ColorFilterMode colorFilterMode)
995 {
996     if (style->isEmpty() || !canEditRichly())
997         return;
998
999     // FIXME: This is wrong for text decorations since m_mutableStyle is empty.
1000     if (!client() || !client()->shouldApplyStyle(style->styleWithResolvedTextDecorations().ptr(), m_frame.selection().toNormalizedRange().get()))
1001         return;
1002
1003     applyStyle(WTFMove(style), editingAction, colorFilterMode);
1004 }
1005
1006 void Editor::applyParagraphStyleToSelection(StyleProperties* style, EditAction editingAction)
1007 {
1008     if (!style || style->isEmpty() || !canEditRichly())
1009         return;
1010     
1011     if (client() && client()->shouldApplyStyle(style, m_frame.selection().toNormalizedRange().get()))
1012         applyParagraphStyle(style, editingAction);
1013 }
1014
1015 bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, const String& value) const
1016 {
1017     if (auto editingStyle = EditingStyle::styleAtSelectionStart(m_frame.selection().selection(), propertyID == CSSPropertyBackgroundColor))
1018         return editingStyle->hasStyle(propertyID, value);
1019     return false;
1020 }
1021
1022 TriState Editor::selectionHasStyle(CSSPropertyID propertyID, const String& value) const
1023 {
1024     return EditingStyle::create(propertyID, value)->triStateOfStyle(m_frame.selection().selection());
1025 }
1026
1027 String Editor::selectionStartCSSPropertyValue(CSSPropertyID propertyID)
1028 {
1029     RefPtr<EditingStyle> selectionStyle = EditingStyle::styleAtSelectionStart(m_frame.selection().selection(),
1030         propertyID == CSSPropertyBackgroundColor);
1031     if (!selectionStyle || !selectionStyle->style())
1032         return String();
1033
1034     if (propertyID == CSSPropertyFontSize)
1035         return String::number(selectionStyle->legacyFontSize(document()));
1036     return selectionStyle->style()->getPropertyValue(propertyID);
1037 }
1038
1039 void Editor::indent()
1040 {
1041     IndentOutdentCommand::create(document(), IndentOutdentCommand::Indent)->apply();
1042 }
1043
1044 void Editor::outdent()
1045 {
1046     IndentOutdentCommand::create(document(), IndentOutdentCommand::Outdent)->apply();
1047 }
1048
1049 static void notifyTextFromControls(Element* startRoot, Element* endRoot)
1050 {
1051     HTMLTextFormControlElement* startingTextControl = enclosingTextFormControl(firstPositionInOrBeforeNode(startRoot));
1052     HTMLTextFormControlElement* endingTextControl = enclosingTextFormControl(firstPositionInOrBeforeNode(endRoot));
1053     if (startingTextControl)
1054         startingTextControl->didEditInnerTextValue();
1055     if (endingTextControl && startingTextControl != endingTextControl)
1056         endingTextControl->didEditInnerTextValue();
1057 }
1058
1059 static bool dispatchBeforeInputEvents(RefPtr<Element> startRoot, RefPtr<Element> endRoot, const AtomicString& inputTypeName, const String& data = { }, RefPtr<DataTransfer>&& dataTransfer = nullptr, const Vector<RefPtr<StaticRange>>& targetRanges = { }, Event::IsCancelable cancelable = Event::IsCancelable::Yes)
1060 {
1061     bool continueWithDefaultBehavior = true;
1062     if (startRoot)
1063         continueWithDefaultBehavior &= dispatchBeforeInputEvent(*startRoot, inputTypeName, data, WTFMove(dataTransfer), targetRanges, cancelable);
1064     if (endRoot && endRoot != startRoot)
1065         continueWithDefaultBehavior &= dispatchBeforeInputEvent(*endRoot, inputTypeName, data, WTFMove(dataTransfer), targetRanges, cancelable);
1066     return continueWithDefaultBehavior;
1067 }
1068
1069 static void dispatchInputEvents(RefPtr<Element> startRoot, RefPtr<Element> endRoot, const AtomicString& inputTypeName, const String& data = { }, RefPtr<DataTransfer>&& dataTransfer = nullptr, const Vector<RefPtr<StaticRange>>& targetRanges = { })
1070 {
1071     if (startRoot)
1072         dispatchInputEvent(*startRoot, inputTypeName, data, WTFMove(dataTransfer), targetRanges);
1073     if (endRoot && endRoot != startRoot)
1074         dispatchInputEvent(*endRoot, inputTypeName, data, WTFMove(dataTransfer), targetRanges);
1075 }
1076
1077 bool Editor::willApplyEditing(CompositeEditCommand& command, Vector<RefPtr<StaticRange>>&& targetRanges) const
1078 {
1079     if (!command.shouldDispatchInputEvents())
1080         return true;
1081
1082     auto* composition = command.composition();
1083     if (!composition)
1084         return true;
1085
1086     return dispatchBeforeInputEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement(), command.inputEventTypeName(),
1087         command.inputEventData(), command.inputEventDataTransfer(), targetRanges, command.isBeforeInputEventCancelable() ? Event::IsCancelable::Yes : Event::IsCancelable::No);
1088 }
1089
1090 void Editor::appliedEditing(CompositeEditCommand& command)
1091 {
1092     LOG(Editing, "Editor %p appliedEditing", this);
1093
1094     document().updateLayout();
1095
1096     ASSERT(command.composition());
1097     auto& composition = *command.composition();
1098     VisibleSelection newSelection(command.endingSelection());
1099
1100     notifyTextFromControls(composition.startingRootEditableElement(), composition.endingRootEditableElement());
1101
1102     if (command.isTopLevelCommand()) {
1103         // Don't clear the typing style with this selection change. We do those things elsewhere if necessary.
1104         OptionSet<FrameSelection::SetSelectionOption> options;
1105         if (command.isDictationCommand())
1106             options.add(FrameSelection::DictationTriggered);
1107
1108         changeSelectionAfterCommand(newSelection, options);
1109     }
1110
1111     if (command.shouldDispatchInputEvents())
1112         dispatchInputEvents(composition.startingRootEditableElement(), composition.endingRootEditableElement(), command.inputEventTypeName(), command.inputEventData(), command.inputEventDataTransfer());
1113
1114     if (command.isTopLevelCommand()) {
1115         updateEditorUINowIfScheduled();
1116
1117         m_alternativeTextController->respondToAppliedEditing(&command);
1118
1119         if (!command.preservesTypingStyle())
1120             m_frame.selection().clearTypingStyle();
1121
1122         // Command will be equal to last edit command only in the case of typing
1123         if (m_lastEditCommand.get() == &command)
1124             ASSERT(command.isTypingCommand());
1125         else {
1126             // Only register a new undo command if the command passed in is
1127             // different from the last command
1128             m_lastEditCommand = &command;
1129             if (client())
1130                 client()->registerUndoStep(m_lastEditCommand->ensureComposition());
1131         }
1132         respondToChangedContents(newSelection);
1133     }
1134 }
1135
1136 bool Editor::willUnapplyEditing(const EditCommandComposition& composition) const
1137 {
1138     return dispatchBeforeInputEvents(composition.startingRootEditableElement(), composition.endingRootEditableElement(), "historyUndo");
1139 }
1140
1141 void Editor::unappliedEditing(EditCommandComposition& composition)
1142 {
1143     document().updateLayout();
1144
1145     notifyTextFromControls(composition.startingRootEditableElement(), composition.endingRootEditableElement());
1146
1147     VisibleSelection newSelection(composition.startingSelection());
1148     changeSelectionAfterCommand(newSelection, FrameSelection::defaultSetSelectionOptions());
1149     dispatchInputEvents(composition.startingRootEditableElement(), composition.endingRootEditableElement(), "historyUndo");
1150
1151     updateEditorUINowIfScheduled();
1152
1153     m_alternativeTextController->respondToUnappliedEditing(&composition);
1154
1155     m_lastEditCommand = nullptr;
1156     if (auto* client = this->client())
1157         client->registerRedoStep(composition);
1158     respondToChangedContents(newSelection);
1159 }
1160
1161 bool Editor::willReapplyEditing(const EditCommandComposition& composition) const
1162 {
1163     return dispatchBeforeInputEvents(composition.startingRootEditableElement(), composition.endingRootEditableElement(), "historyRedo");
1164 }
1165
1166 void Editor::reappliedEditing(EditCommandComposition& composition)
1167 {
1168     document().updateLayout();
1169
1170     notifyTextFromControls(composition.startingRootEditableElement(), composition.endingRootEditableElement());
1171
1172     VisibleSelection newSelection(composition.endingSelection());
1173     changeSelectionAfterCommand(newSelection, FrameSelection::defaultSetSelectionOptions());
1174     dispatchInputEvents(composition.startingRootEditableElement(), composition.endingRootEditableElement(), "historyRedo");
1175     
1176     updateEditorUINowIfScheduled();
1177
1178     m_lastEditCommand = nullptr;
1179     if (auto* client = this->client())
1180         client->registerUndoStep(composition);
1181     respondToChangedContents(newSelection);
1182 }
1183
1184 Editor::Editor(Frame& frame)
1185     : m_frame(frame)
1186     , m_killRing(std::make_unique<PAL::KillRing>())
1187     , m_spellChecker(std::make_unique<SpellChecker>(frame))
1188     , m_alternativeTextController(std::make_unique<AlternativeTextController>(frame))
1189     , m_editorUIUpdateTimer(*this, &Editor::editorUIUpdateTimerFired)
1190 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
1191     , m_telephoneNumberDetectionUpdateTimer(*this, &Editor::scanSelectionForTelephoneNumbers)
1192 #endif
1193 {
1194 }
1195
1196 Editor::~Editor() = default;
1197
1198 void Editor::clear()
1199 {
1200     m_lastEditCommand = nullptr;
1201     if (m_compositionNode) {
1202         m_compositionNode = nullptr;
1203         if (EditorClient* client = this->client())
1204             client->discardedComposition(&m_frame);
1205     }
1206     m_customCompositionUnderlines.clear();
1207     m_shouldStyleWithCSS = false;
1208     m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv;
1209     m_mark = { };
1210     m_oldSelectionForEditorUIUpdate = { };
1211     m_editorUIUpdateTimer.stop();
1212
1213 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
1214     m_telephoneNumberDetectionUpdateTimer.stop();
1215     m_detectedTelephoneNumberRanges.clear();
1216 #endif
1217 }
1218
1219 bool Editor::insertText(const String& text, Event* triggeringEvent, TextEventInputType inputType)
1220 {
1221     return m_frame.eventHandler().handleTextInputEvent(text, triggeringEvent, inputType);
1222 }
1223
1224 bool Editor::insertTextForConfirmedComposition(const String& text)
1225 {
1226     return m_frame.eventHandler().handleTextInputEvent(text, 0, TextEventInputComposition);
1227 }
1228
1229 bool Editor::insertDictatedText(const String& text, const Vector<DictationAlternative>& dictationAlternatives, Event* triggeringEvent)
1230 {
1231     return m_alternativeTextController->insertDictatedText(text, dictationAlternatives, triggeringEvent);
1232 }
1233
1234 bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectInsertedText, TextEvent* triggeringEvent)
1235 {
1236     if (text.isEmpty())
1237         return false;
1238
1239     VisibleSelection selection = selectionForCommand(triggeringEvent);
1240     if (!selection.isContentEditable())
1241         return false;
1242     RefPtr<Range> range = selection.toNormalizedRange();
1243
1244     if (!shouldInsertText(text, range.get(), EditorInsertAction::Typed))
1245         return true;
1246
1247     updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0]));
1248
1249     bool shouldConsiderApplyingAutocorrection = false;
1250     if (text == " " || text == "\t")
1251         shouldConsiderApplyingAutocorrection = true;
1252
1253     if (text.length() == 1 && u_ispunct(text[0]) && !isAmbiguousBoundaryCharacter(text[0]))
1254         shouldConsiderApplyingAutocorrection = true;
1255
1256     bool autocorrectionWasApplied = shouldConsiderApplyingAutocorrection && m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1257
1258     // Get the selection to use for the event that triggered this insertText.
1259     // If the event handler changed the selection, we may want to use a different selection
1260     // that is contained in the event target.
1261     selection = selectionForCommand(triggeringEvent);
1262     if (selection.isContentEditable()) {
1263         if (Node* selectionStart = selection.start().deprecatedNode()) {
1264             Ref<Document> document(selectionStart->document());
1265
1266             // Insert the text
1267             if (triggeringEvent && triggeringEvent->isDictation())
1268                 DictationCommand::insertText(document, text, triggeringEvent->dictationAlternatives(), selection);
1269             else {
1270                 TypingCommand::Options options = 0;
1271                 if (selectInsertedText)
1272                     options |= TypingCommand::SelectInsertedText;
1273                 if (autocorrectionWasApplied)
1274                     options |= TypingCommand::RetainAutocorrectionIndicator;
1275                 if (triggeringEvent && triggeringEvent->isAutocompletion())
1276                     options |= TypingCommand::IsAutocompletion;
1277                 TypingCommand::insertText(document, text, selection, options, triggeringEvent && triggeringEvent->isComposition() ? TypingCommand::TextCompositionFinal : TypingCommand::TextCompositionNone);
1278             }
1279
1280             // Reveal the current selection
1281             if (Frame* editedFrame = document->frame())
1282                 if (Page* page = editedFrame->page()) {
1283                     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
1284                     page->focusController().focusedOrMainFrame().selection().revealSelection(revealMode, ScrollAlignment::alignCenterIfNeeded);
1285                 }
1286         }
1287     }
1288
1289     return true;
1290 }
1291
1292 bool Editor::insertLineBreak()
1293 {
1294     if (!canEdit())
1295         return false;
1296
1297     if (!shouldInsertText("\n", m_frame.selection().toNormalizedRange().get(), EditorInsertAction::Typed))
1298         return true;
1299
1300     VisiblePosition caret = m_frame.selection().selection().visibleStart();
1301     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
1302     bool autocorrectionIsApplied = m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1303     TypingCommand::insertLineBreak(document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
1304     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
1305
1306     return true;
1307 }
1308
1309 bool Editor::insertParagraphSeparator()
1310 {
1311     if (!canEdit())
1312         return false;
1313
1314     if (!canEditRichly())
1315         return insertLineBreak();
1316
1317     if (!shouldInsertText("\n", m_frame.selection().toNormalizedRange().get(), EditorInsertAction::Typed))
1318         return true;
1319
1320     VisiblePosition caret = m_frame.selection().selection().visibleStart();
1321     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
1322     bool autocorrectionIsApplied = m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1323     TypingCommand::insertParagraphSeparator(document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
1324     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
1325
1326     return true;
1327 }
1328
1329 bool Editor::insertParagraphSeparatorInQuotedContent()
1330 {
1331     // FIXME: Why is this missing calls to canEdit, canEditRichly, etc.?
1332     TypingCommand::insertParagraphSeparatorInQuotedContent(document());
1333     revealSelectionAfterEditingOperation();
1334     return true;
1335 }
1336
1337 void Editor::cut()
1338 {
1339     if (tryDHTMLCut())
1340         return; // DHTML did the whole operation
1341     if (!canCut()) {
1342         PAL::systemBeep();
1343         return;
1344     }
1345
1346     performCutOrCopy(CutAction);
1347 }
1348
1349 void Editor::copy()
1350 {
1351     if (tryDHTMLCopy())
1352         return; // DHTML did the whole operation
1353     if (!canCopy()) {
1354         PAL::systemBeep();
1355         return;
1356     }
1357
1358     performCutOrCopy(CopyAction);
1359 }
1360
1361 void Editor::postTextStateChangeNotificationForCut(const String& text, const VisibleSelection& selection)
1362 {
1363     if (!AXObjectCache::accessibilityEnabled())
1364         return;
1365     if (!text.length())
1366         return;
1367     AXObjectCache* cache = document().existingAXObjectCache();
1368     if (!cache)
1369         return;
1370     cache->postTextStateChangeNotification(selection.start().anchorNode(), AXTextEditTypeCut, text, selection.start());
1371 }
1372
1373 void Editor::performCutOrCopy(EditorActionSpecifier action)
1374 {
1375     RefPtr<Range> selection = selectedRange();
1376     willWriteSelectionToPasteboard(selection.get());
1377     if (action == CutAction) {
1378         if (!shouldDeleteRange(selection.get()))
1379             return;
1380
1381         updateMarkersForWordsAffectedByEditing(true);
1382     }
1383
1384     if (enclosingTextFormControl(m_frame.selection().selection().start()))
1385         Pasteboard::createForCopyAndPaste()->writePlainText(selectedTextForDataTransfer(), canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace : Pasteboard::CannotSmartReplace);
1386     else {
1387         HTMLImageElement* imageElement = nullptr;
1388         if (action == CopyAction)
1389             imageElement = imageElementFromImageDocument(document());
1390
1391         if (imageElement) {
1392 #if !PLATFORM(WIN)
1393             writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), *imageElement, document().url(), document().title());
1394 #else
1395             // FIXME: Delete after <http://webkit.org/b/177618> lands.
1396             Pasteboard::createForCopyAndPaste()->writeImage(*imageElement, document().url(), document().title());
1397 #endif
1398         } else {
1399 #if !PLATFORM(WIN)
1400             writeSelectionToPasteboard(*Pasteboard::createForCopyAndPaste());
1401 #else
1402             // FIXME: Delete after <http://webkit.org/b/177618> lands.
1403             Pasteboard::createForCopyAndPaste()->writeSelection(*selection, canSmartCopyOrDelete(), m_frame, IncludeImageAltTextForDataTransfer);
1404 #endif
1405         }
1406     }
1407
1408     didWriteSelectionToPasteboard();
1409     if (action == CutAction) {
1410         String text;
1411         if (AXObjectCache::accessibilityEnabled())
1412             text = AccessibilityObject::stringForVisiblePositionRange(m_frame.selection().selection());
1413         deleteSelectionWithSmartDelete(canSmartCopyOrDelete(), EditAction::Cut);
1414         if (AXObjectCache::accessibilityEnabled())
1415             postTextStateChangeNotificationForCut(text, m_frame.selection().selection());
1416     }
1417 }
1418
1419 void Editor::paste()
1420 {
1421     paste(*Pasteboard::createForCopyAndPaste());
1422 }
1423
1424 void Editor::paste(Pasteboard& pasteboard)
1425 {
1426     if (!dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Paste))
1427         return; // DHTML did the whole operation
1428     if (!canPaste())
1429         return;
1430     updateMarkersForWordsAffectedByEditing(false);
1431     ResourceCacheValidationSuppressor validationSuppressor(document().cachedResourceLoader());
1432     if (m_frame.selection().selection().isContentRichlyEditable())
1433         pasteWithPasteboard(&pasteboard, { PasteOption::AllowPlainText });
1434     else
1435         pasteAsPlainTextWithPasteboard(pasteboard);
1436 }
1437
1438 void Editor::pasteAsPlainText()
1439 {
1440     if (!dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::PasteAsPlainText))
1441         return;
1442     if (!canPaste())
1443         return;
1444     updateMarkersForWordsAffectedByEditing(false);
1445     pasteAsPlainTextWithPasteboard(*Pasteboard::createForCopyAndPaste());
1446 }
1447
1448 void Editor::pasteAsQuotation()
1449 {
1450     if (!dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::PasteAsQuotation))
1451         return;
1452     if (!canPaste())
1453         return;
1454     updateMarkersForWordsAffectedByEditing(false);
1455     ResourceCacheValidationSuppressor validationSuppressor(document().cachedResourceLoader());
1456     auto pasteboard = Pasteboard::createForCopyAndPaste();
1457     if (m_frame.selection().selection().isContentRichlyEditable())
1458         pasteWithPasteboard(pasteboard.get(), { PasteOption::AllowPlainText, PasteOption::AsQuotation });
1459     else
1460         pasteAsPlainTextWithPasteboard(*pasteboard);
1461 }
1462
1463 void Editor::quoteFragmentForPasting(DocumentFragment& fragment)
1464 {
1465     auto blockQuote = HTMLQuoteElement::create(blockquoteTag, document());
1466     blockQuote->setAttributeWithoutSynchronization(typeAttr, AtomicString("cite"));
1467     blockQuote->setAttributeWithoutSynchronization(classAttr, AtomicString(ApplePasteAsQuotation));
1468
1469     auto childNode = fragment.firstChild();
1470
1471     if (childNode) {
1472         while (childNode) {
1473             blockQuote->appendChild(*childNode);
1474             childNode = fragment.firstChild();
1475         }
1476     } else
1477         blockQuote->appendChild(HTMLBRElement::create(document()));
1478
1479     fragment.appendChild(blockQuote);
1480 }
1481
1482 void Editor::performDelete()
1483 {
1484     if (!canDelete()) {
1485         PAL::systemBeep();
1486         return;
1487     }
1488
1489     addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
1490     deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
1491
1492     // clear the "start new kill ring sequence" setting, because it was set to true
1493     // when the selection was updated by deleting the range
1494     setStartNewKillRingSequence(false);
1495 }
1496
1497 void Editor::changeSelectionListType()
1498 {
1499     if (auto type = ChangeListTypeCommand::listConversionType(document()))
1500         ChangeListTypeCommand::create(document(), *type)->apply();
1501 }
1502
1503 void Editor::simplifyMarkup(Node* startNode, Node* endNode)
1504 {
1505     if (!startNode)
1506         return;
1507     if (endNode) {
1508         if (&startNode->document() != &endNode->document())
1509             return;
1510         // check if start node is before endNode
1511         Node* node = startNode;
1512         while (node && node != endNode)
1513             node = NodeTraversal::next(*node);
1514         if (!node)
1515             return;
1516     }
1517     
1518     SimplifyMarkupCommand::create(document(), startNode, endNode ? NodeTraversal::next(*endNode) : nullptr)->apply();
1519 }
1520
1521 void Editor::copyURL(const URL& url, const String& title)
1522 {
1523     copyURL(url, title, *Pasteboard::createForCopyAndPaste());
1524 }
1525
1526 void Editor::copyURL(const URL& url, const String& title, Pasteboard& pasteboard)
1527 {
1528     PasteboardURL pasteboardURL;
1529     pasteboardURL.url = url;
1530     pasteboardURL.title = title;
1531
1532 #if PLATFORM(MAC)
1533     pasteboardURL.userVisibleForm = userVisibleString(url);
1534 #endif
1535
1536     pasteboard.write(pasteboardURL);
1537 }
1538
1539 PasteboardWriterData::URLData Editor::pasteboardWriterURL(const URL& url, const String& title)
1540 {
1541     PasteboardWriterData::URLData result;
1542
1543     result.url = url;
1544     result.title = title;
1545 #if PLATFORM(MAC)
1546     result.userVisibleForm = userVisibleString(url);
1547 #endif
1548
1549     return result;
1550 }
1551
1552 #if !PLATFORM(IOS_FAMILY)
1553
1554 void Editor::copyImage(const HitTestResult& result)
1555 {
1556     Element* element = result.innerNonSharedElement();
1557     if (!element)
1558         return;
1559
1560     URL url = result.absoluteLinkURL();
1561     if (url.isEmpty())
1562         url = result.absoluteImageURL();
1563
1564 #if !PLATFORM(WIN)
1565     writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), *element, url, result.altDisplayString());
1566 #else
1567     // FIXME: Delete after <http://webkit.org/b/177618> lands.
1568     Pasteboard::createForCopyAndPaste()->writeImage(*element, url, result.altDisplayString());
1569 #endif
1570 }
1571
1572 #endif
1573
1574 bool Editor::isContinuousSpellCheckingEnabled() const
1575 {
1576     return client() && client()->isContinuousSpellCheckingEnabled();
1577 }
1578
1579 void Editor::toggleContinuousSpellChecking()
1580 {
1581     if (client())
1582         client()->toggleContinuousSpellChecking();
1583 }
1584
1585 bool Editor::isGrammarCheckingEnabled()
1586 {
1587     return client() && client()->isGrammarCheckingEnabled();
1588 }
1589
1590 void Editor::toggleGrammarChecking()
1591 {
1592     if (client())
1593         client()->toggleGrammarChecking();
1594 }
1595
1596 int Editor::spellCheckerDocumentTag()
1597 {
1598     return client() ? client()->spellCheckerDocumentTag() : 0;
1599 }
1600
1601 #if USE(APPKIT)
1602
1603 void Editor::uppercaseWord()
1604 {
1605     if (client())
1606         client()->uppercaseWord();
1607 }
1608
1609 void Editor::lowercaseWord()
1610 {
1611     if (client())
1612         client()->lowercaseWord();
1613 }
1614
1615 void Editor::capitalizeWord()
1616 {
1617     if (client())
1618         client()->capitalizeWord();
1619 }
1620     
1621 #endif
1622
1623 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1624
1625 void Editor::showSubstitutionsPanel()
1626 {
1627     if (!client()) {
1628         LOG_ERROR("No NSSpellChecker");
1629         return;
1630     }
1631
1632     if (client()->substitutionsPanelIsShowing()) {
1633         client()->showSubstitutionsPanel(false);
1634         return;
1635     }
1636     client()->showSubstitutionsPanel(true);
1637 }
1638
1639 bool Editor::substitutionsPanelIsShowing()
1640 {
1641     if (!client())
1642         return false;
1643     return client()->substitutionsPanelIsShowing();
1644 }
1645
1646 void Editor::toggleSmartInsertDelete()
1647 {
1648     if (client())
1649         client()->toggleSmartInsertDelete();
1650 }
1651
1652 bool Editor::isAutomaticQuoteSubstitutionEnabled()
1653 {
1654     return client() && client()->isAutomaticQuoteSubstitutionEnabled();
1655 }
1656
1657 void Editor::toggleAutomaticQuoteSubstitution()
1658 {
1659     if (client())
1660         client()->toggleAutomaticQuoteSubstitution();
1661 }
1662
1663 bool Editor::isAutomaticLinkDetectionEnabled()
1664 {
1665     return client() && client()->isAutomaticLinkDetectionEnabled();
1666 }
1667
1668 void Editor::toggleAutomaticLinkDetection()
1669 {
1670     if (client())
1671         client()->toggleAutomaticLinkDetection();
1672 }
1673
1674 bool Editor::isAutomaticDashSubstitutionEnabled()
1675 {
1676     return client() && client()->isAutomaticDashSubstitutionEnabled();
1677 }
1678
1679 void Editor::toggleAutomaticDashSubstitution()
1680 {
1681     if (client())
1682         client()->toggleAutomaticDashSubstitution();
1683 }
1684
1685 bool Editor::isAutomaticTextReplacementEnabled()
1686 {
1687     return client() && client()->isAutomaticTextReplacementEnabled();
1688 }
1689
1690 void Editor::toggleAutomaticTextReplacement()
1691 {
1692     if (client())
1693         client()->toggleAutomaticTextReplacement();
1694 }
1695
1696 bool Editor::isAutomaticSpellingCorrectionEnabled()
1697 {
1698     return m_alternativeTextController->isAutomaticSpellingCorrectionEnabled();
1699 }
1700
1701 void Editor::toggleAutomaticSpellingCorrection()
1702 {
1703     if (client())
1704         client()->toggleAutomaticSpellingCorrection();
1705 }
1706
1707 #endif
1708
1709 bool Editor::shouldEndEditing(Range* range)
1710 {
1711     return client() && client()->shouldEndEditing(range);
1712 }
1713
1714 bool Editor::shouldBeginEditing(Range* range)
1715 {
1716     return client() && client()->shouldBeginEditing(range);
1717 }
1718
1719 void Editor::clearUndoRedoOperations()
1720 {
1721     if (client())
1722         client()->clearUndoRedoOperations();
1723 }
1724
1725 bool Editor::canUndo() const
1726 {
1727     return client() && client()->canUndo();
1728 }
1729
1730 void Editor::undo()
1731 {
1732     if (client())
1733         client()->undo();
1734 }
1735
1736 bool Editor::canRedo() const
1737 {
1738     return client() && client()->canRedo();
1739 }
1740
1741 void Editor::redo()
1742 {
1743     if (client())
1744         client()->redo();
1745 }
1746
1747 void Editor::registerCustomUndoStep(Ref<CustomUndoStep>&& undoStep)
1748 {
1749     ASSERT(RuntimeEnabledFeatures::sharedFeatures().undoManagerAPIEnabled());
1750     if (auto* client = this->client())
1751         client->registerUndoStep(WTFMove(undoStep));
1752 }
1753
1754 void Editor::didBeginEditing()
1755 {
1756     if (client())
1757         client()->didBeginEditing();
1758 }
1759
1760 void Editor::didEndEditing()
1761 {
1762     if (client())
1763         client()->didEndEditing();
1764 }
1765
1766 void Editor::willWriteSelectionToPasteboard(Range* range)
1767 {
1768     if (client())
1769         client()->willWriteSelectionToPasteboard(range);
1770 }
1771
1772 void Editor::didWriteSelectionToPasteboard()
1773 {
1774     if (client())
1775         client()->didWriteSelectionToPasteboard();
1776 }
1777
1778 void Editor::toggleBold()
1779 {
1780     command("ToggleBold").execute();
1781 }
1782
1783 void Editor::toggleUnderline()
1784 {
1785     command("ToggleUnderline").execute();
1786 }
1787
1788 void Editor::setBaseWritingDirection(WritingDirection direction)
1789 {
1790 #if PLATFORM(IOS_FAMILY)
1791     if (inSameParagraph(m_frame.selection().selection().visibleStart(), m_frame.selection().selection().visibleEnd()) && 
1792         baseWritingDirectionForSelectionStart() == direction)
1793         return;
1794 #endif
1795         
1796     Element* focusedElement = document().focusedElement();
1797     if (focusedElement && focusedElement->isTextField()) {
1798         if (direction == WritingDirection::Natural)
1799             return;
1800
1801         auto& focusedFormElement = downcast<HTMLTextFormControlElement>(*focusedElement);
1802         auto directionValue = direction == WritingDirection::LeftToRight ? "ltr" : "rtl";
1803         auto writingDirectionInputTypeName = inputTypeNameForEditingAction(EditAction::SetBlockWritingDirection);
1804         if (!dispatchBeforeInputEvent(focusedFormElement, writingDirectionInputTypeName, directionValue))
1805             return;
1806
1807         focusedFormElement.setAttributeWithoutSynchronization(dirAttr, directionValue);
1808         dispatchInputEvent(focusedFormElement, writingDirectionInputTypeName, directionValue);
1809         document().updateStyleIfNeeded();
1810         return;
1811     }
1812
1813     auto style = MutableStyleProperties::create();
1814     style->setProperty(CSSPropertyDirection, direction == WritingDirection::LeftToRight ? "ltr" : direction == WritingDirection::RightToLeft ? "rtl" : "inherit", false);
1815     applyParagraphStyleToSelection(style.ptr(), EditAction::SetBlockWritingDirection);
1816 }
1817
1818 WritingDirection Editor::baseWritingDirectionForSelectionStart() const
1819 {
1820     auto result = WritingDirection::LeftToRight;
1821
1822     Position pos = m_frame.selection().selection().visibleStart().deepEquivalent();
1823     Node* node = pos.deprecatedNode();
1824     if (!node)
1825         return result;
1826
1827     auto renderer = node->renderer();
1828     if (!renderer)
1829         return result;
1830
1831     if (!renderer->isRenderBlockFlow()) {
1832         renderer = renderer->containingBlock();
1833         if (!renderer)
1834             return result;
1835     }
1836
1837     switch (renderer->style().direction()) {
1838     case TextDirection::LTR:
1839         return WritingDirection::LeftToRight;
1840     case TextDirection::RTL:
1841         return WritingDirection::RightToLeft;
1842     }
1843     
1844     return result;
1845 }
1846
1847 void Editor::selectComposition()
1848 {
1849     RefPtr<Range> range = compositionRange();
1850     if (!range)
1851         return;
1852     
1853     // The composition can start inside a composed character sequence, so we have to override checks.
1854     // See <http://bugs.webkit.org/show_bug.cgi?id=15781>
1855     VisibleSelection selection;
1856     selection.setWithoutValidation(range->startPosition(), range->endPosition());
1857     m_frame.selection().setSelection(selection, { });
1858 }
1859
1860 void Editor::confirmComposition()
1861 {
1862     if (!m_compositionNode)
1863         return;
1864     setComposition(m_compositionNode->data().substring(m_compositionStart, m_compositionEnd - m_compositionStart), ConfirmComposition);
1865 }
1866
1867 void Editor::cancelComposition()
1868 {
1869     if (!m_compositionNode)
1870         return;
1871     setComposition(emptyString(), CancelComposition);
1872 }
1873
1874 bool Editor::cancelCompositionIfSelectionIsInvalid()
1875 {
1876     unsigned start;
1877     unsigned end;
1878     if (!hasComposition() || ignoreSelectionChanges() || getCompositionSelection(start, end))
1879         return false;
1880
1881     cancelComposition();
1882     return true;
1883 }
1884
1885 void Editor::confirmComposition(const String& text)
1886 {
1887     setComposition(text, ConfirmComposition);
1888 }
1889
1890 class SetCompositionScope {
1891 public:
1892     SetCompositionScope(Frame& frame)
1893         : m_frame(frame)
1894         , m_typingGestureIndicator(frame)
1895     {
1896         m_frame->editor().setIgnoreSelectionChanges(true);
1897     }
1898
1899     ~SetCompositionScope()
1900     {
1901         m_frame->editor().setIgnoreSelectionChanges(false);
1902         if (auto* editorClient = m_frame->editor().client())
1903             editorClient->didUpdateComposition();
1904     }
1905
1906     Ref<Frame> m_frame;
1907     UserTypingGestureIndicator m_typingGestureIndicator;
1908 };
1909
1910 void Editor::setComposition(const String& text, SetCompositionMode mode)
1911 {
1912     ASSERT(mode == ConfirmComposition || mode == CancelComposition);
1913     SetCompositionScope setCompositionScope(m_frame);
1914
1915     if (mode == CancelComposition)
1916         ASSERT(text == emptyString());
1917     else
1918         selectComposition();
1919
1920     m_compositionNode = nullptr;
1921     m_customCompositionUnderlines.clear();
1922
1923     if (m_frame.selection().isNone())
1924         return;
1925
1926     // Always delete the current composition before inserting the finalized composition text if we're confirming our composition.
1927     // Our default behavior (if the beforeinput event is not prevented) is to insert the finalized composition text back in.
1928     // We pass TypingCommand::TextCompositionPending here to indicate that we are deleting the pending composition.
1929     if (mode != CancelComposition)
1930         TypingCommand::deleteSelection(document(), 0, TypingCommand::TextCompositionPending);
1931
1932     insertTextForConfirmedComposition(text);
1933
1934     if (auto* target = document().focusedElement())
1935         target->dispatchEvent(CompositionEvent::create(eventNames().compositionendEvent, document().windowProxy(), text));
1936
1937     if (mode == CancelComposition) {
1938         // An open typing command that disagrees about current selection would cause issues with typing later on.
1939         TypingCommand::closeTyping(&m_frame);
1940     }
1941 }
1942
1943 void Editor::setComposition(const String& text, const Vector<CompositionUnderline>& underlines, unsigned selectionStart, unsigned selectionEnd)
1944 {
1945     SetCompositionScope setCompositionScope(m_frame);
1946
1947     // Updates styles before setting selection for composition to prevent
1948     // inserting the previous composition text into text nodes oddly.
1949     // See https://bugs.webkit.org/show_bug.cgi?id=46868
1950     document().updateStyleIfNeeded();
1951
1952     selectComposition();
1953
1954     if (m_frame.selection().isNone())
1955         return;
1956
1957     String originalText = selectedText();
1958     bool isStartingToRecomposeExistingRange = !text.isEmpty() && selectionStart < selectionEnd && !hasComposition();
1959     if (isStartingToRecomposeExistingRange) {
1960         // We pass TypingCommand::TextCompositionFinal here to indicate that we are removing composition text that has been finalized.
1961         TypingCommand::deleteSelection(document(), 0, TypingCommand::TextCompositionFinal);
1962         const VisibleSelection& currentSelection = m_frame.selection().selection();
1963         if (currentSelection.isRange()) {
1964             // If deletion was prevented, then we need to collapse the selection to the end so that the original text will not be recomposed.
1965             m_frame.selection().setSelection({ currentSelection.end(), currentSelection.end() });
1966         }
1967     }
1968
1969 #if PLATFORM(IOS_FAMILY)
1970     client()->startDelayingAndCoalescingContentChangeNotifications();
1971 #endif
1972
1973     Element* target = document().focusedElement();
1974     if (target) {
1975         // Dispatch an appropriate composition event to the focused node.
1976         // We check the composition status and choose an appropriate composition event since this
1977         // function is used for three purposes:
1978         // 1. Starting a new composition.
1979         //    Send a compositionstart and a compositionupdate event when this function creates
1980         //    a new composition node, i.e.
1981         //    m_compositionNode == 0 && !text.isEmpty().
1982         //    Sending a compositionupdate event at this time ensures that at least one
1983         //    compositionupdate event is dispatched.
1984         // 2. Updating the existing composition node.
1985         //    Send a compositionupdate event when this function updates the existing composition
1986         //    node, i.e. m_compositionNode != 0 && !text.isEmpty().
1987         // 3. Canceling the ongoing composition.
1988         //    Send a compositionend event when function deletes the existing composition node, i.e.
1989         //    m_compositionNode != 0 && test.isEmpty().
1990         RefPtr<CompositionEvent> event;
1991         if (!m_compositionNode) {
1992             // We should send a compositionstart event only when the given text is not empty because this
1993             // function doesn't create a composition node when the text is empty.
1994             if (!text.isEmpty()) {
1995                 target->dispatchEvent(CompositionEvent::create(eventNames().compositionstartEvent, document().windowProxy(), originalText));
1996                 event = CompositionEvent::create(eventNames().compositionupdateEvent, document().windowProxy(), text);
1997             }
1998         } else if (!text.isEmpty())
1999             event = CompositionEvent::create(eventNames().compositionupdateEvent, document().windowProxy(), text);
2000
2001         if (event)
2002             target->dispatchEvent(*event);
2003     }
2004
2005     // If text is empty, then delete the old composition here.  If text is non-empty, InsertTextCommand::input
2006     // will delete the old composition with an optimized replace operation.
2007     if (text.isEmpty()) {
2008         TypingCommand::deleteSelection(document(), TypingCommand::PreventSpellChecking, TypingCommand::TextCompositionPending);
2009         if (target)
2010             target->dispatchEvent(CompositionEvent::create(eventNames().compositionendEvent, document().windowProxy(), text));
2011     }
2012
2013     m_compositionNode = nullptr;
2014     m_customCompositionUnderlines.clear();
2015
2016     if (!text.isEmpty()) {
2017         TypingCommand::insertText(document(), text, TypingCommand::SelectInsertedText | TypingCommand::PreventSpellChecking, TypingCommand::TextCompositionPending);
2018
2019         // Find out what node has the composition now.
2020         Position base = m_frame.selection().selection().base().downstream();
2021         Position extent = m_frame.selection().selection().extent();
2022         Node* baseNode = base.deprecatedNode();
2023         unsigned baseOffset = base.deprecatedEditingOffset();
2024         Node* extentNode = extent.deprecatedNode();
2025         unsigned extentOffset = extent.deprecatedEditingOffset();
2026
2027         if (is<Text>(baseNode) && baseNode == extentNode && baseOffset + text.length() == extentOffset) {
2028             m_compositionNode = downcast<Text>(baseNode);
2029             m_compositionStart = baseOffset;
2030             m_compositionEnd = extentOffset;
2031             m_customCompositionUnderlines = underlines;
2032             for (auto& underline : m_customCompositionUnderlines) {
2033                 underline.startOffset += baseOffset;
2034                 underline.endOffset += baseOffset;
2035             }
2036             if (baseNode->renderer())
2037                 baseNode->renderer()->repaint();
2038
2039             unsigned start = std::min(baseOffset + selectionStart, extentOffset);
2040             unsigned end = std::min(std::max(start, baseOffset + selectionEnd), extentOffset);
2041             auto selectedRange = Range::create(baseNode->document(), baseNode, start, baseNode, end);
2042             m_frame.selection().setSelectedRange(selectedRange.ptr(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::No);
2043         }
2044     }
2045
2046 #if PLATFORM(IOS_FAMILY)        
2047     client()->stopDelayingAndCoalescingContentChangeNotifications();
2048 #endif
2049 }
2050
2051 void Editor::ignoreSpelling()
2052 {
2053     if (!client())
2054         return;
2055         
2056     RefPtr<Range> selectedRange = m_frame.selection().toNormalizedRange();
2057     if (selectedRange)
2058         document().markers().removeMarkers(*selectedRange, DocumentMarker::Spelling);
2059
2060     String text = selectedText();
2061     ASSERT(text.length());
2062     textChecker()->ignoreWordInSpellDocument(text);
2063 }
2064
2065 void Editor::learnSpelling()
2066 {
2067     if (!client())
2068         return;
2069         
2070     // FIXME: On Mac OS X, when use "learn" button on "Spelling and Grammar" panel, we don't call this function. It should remove misspelling markers around the learned word, see <rdar://problem/5396072>.
2071
2072     RefPtr<Range> selectedRange = m_frame.selection().toNormalizedRange();
2073     if (selectedRange)
2074         document().markers().removeMarkers(*selectedRange, DocumentMarker::Spelling);
2075
2076     String text = selectedText();
2077     ASSERT(text.length());
2078     textChecker()->learnWord(text);
2079 }
2080
2081 #if !PLATFORM(IOS_FAMILY)
2082
2083 void Editor::advanceToNextMisspelling(bool startBeforeSelection)
2084 {
2085     Ref<Frame> protection(m_frame);
2086
2087     // The basic approach is to search in two phases - from the selection end to the end of the doc, and
2088     // then we wrap and search from the doc start to (approximately) where we started.
2089     
2090     // Start at the end of the selection, search to edge of document.  Starting at the selection end makes
2091     // repeated "check spelling" commands work.
2092     VisibleSelection selection(m_frame.selection().selection());
2093     Ref<Range> spellingSearchRange = rangeOfContents(document());
2094
2095     bool startedWithSelection = false;
2096     if (selection.start().deprecatedNode()) {
2097         startedWithSelection = true;
2098         if (startBeforeSelection) {
2099             VisiblePosition start(selection.visibleStart());
2100             // We match AppKit's rule: Start 1 character before the selection.
2101             VisiblePosition oneBeforeStart = start.previous();
2102             setStart(spellingSearchRange.ptr(), oneBeforeStart.isNotNull() ? oneBeforeStart : start);
2103         } else
2104             setStart(spellingSearchRange.ptr(), selection.visibleEnd());
2105     }
2106
2107     Position position = spellingSearchRange->startPosition();
2108     if (!isEditablePosition(position)) {
2109         // This shouldn't happen in very often because the Spelling menu items aren't enabled unless the
2110         // selection is editable.
2111         // This can happen in Mail for a mix of non-editable and editable content (like Stationary), 
2112         // when spell checking the whole document before sending the message.
2113         // In that case the document might not be editable, but there are editable pockets that need to be spell checked.
2114
2115         position = VisiblePosition(firstEditablePositionAfterPositionInRoot(position, document().documentElement())).deepEquivalent();
2116         if (position.isNull())
2117             return;
2118         
2119         Position rangeCompliantPosition = position.parentAnchoredEquivalent();
2120         if (rangeCompliantPosition.deprecatedNode())
2121             spellingSearchRange->setStart(*rangeCompliantPosition.deprecatedNode(), rangeCompliantPosition.deprecatedEditingOffset());
2122         startedWithSelection = false; // won't need to wrap
2123     }
2124     
2125     // topNode defines the whole range we want to operate on 
2126     auto* topNode = highestEditableRoot(position);
2127     // FIXME: lastOffsetForEditing() is wrong here if editingIgnoresContent(highestEditableRoot()) returns true (e.g. a <table>)
2128     if (topNode)
2129         spellingSearchRange->setEnd(*topNode, lastOffsetForEditing(*topNode));
2130
2131     // If spellingSearchRange starts in the middle of a word, advance to the next word so we start checking
2132     // at a word boundary. Going back by one char and then forward by a word does the trick.
2133     if (startedWithSelection) {
2134         VisiblePosition oneBeforeStart = startVisiblePosition(spellingSearchRange.ptr(), DOWNSTREAM).previous();
2135         if (oneBeforeStart.isNotNull())
2136             setStart(spellingSearchRange.ptr(), endOfWord(oneBeforeStart));
2137         // else we were already at the start of the editable node
2138     }
2139
2140     if (spellingSearchRange->collapsed())
2141         return; // nothing to search in
2142     
2143     // Get the spell checker if it is available
2144     if (!client())
2145         return;
2146         
2147     // We go to the end of our first range instead of the start of it, just to be sure
2148     // we don't get foiled by any word boundary problems at the start.  It means we might
2149     // do a tiny bit more searching.
2150     Node& searchEndNodeAfterWrap = spellingSearchRange->endContainer();
2151     int searchEndOffsetAfterWrap = spellingSearchRange->endOffset();
2152     
2153     int misspellingOffset = 0;
2154     GrammarDetail grammarDetail;
2155     int grammarPhraseOffset = 0;
2156     RefPtr<Range> grammarSearchRange;
2157     String badGrammarPhrase;
2158     String misspelledWord;
2159
2160     bool isSpelling = true;
2161     int foundOffset = 0;
2162     String foundItem;
2163     RefPtr<Range> firstMisspellingRange;
2164     if (unifiedTextCheckerEnabled()) {
2165         grammarSearchRange = spellingSearchRange->cloneRange();
2166         foundItem = TextCheckingHelper(*client(), spellingSearchRange).findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
2167         if (isSpelling) {
2168             misspelledWord = foundItem;
2169             misspellingOffset = foundOffset;
2170         } else {
2171             badGrammarPhrase = foundItem;
2172             grammarPhraseOffset = foundOffset;
2173         }
2174     } else {
2175         misspelledWord = TextCheckingHelper(*client(), spellingSearchRange).findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);
2176
2177 #if USE(GRAMMAR_CHECKING)
2178         grammarSearchRange = spellingSearchRange->cloneRange();
2179         if (!misspelledWord.isEmpty()) {
2180             // Stop looking at start of next misspelled word
2181             CharacterIterator chars(*grammarSearchRange);
2182             chars.advance(misspellingOffset);
2183             grammarSearchRange->setEnd(chars.range()->startContainer(), chars.range()->startOffset());
2184         }
2185     
2186         if (isGrammarCheckingEnabled())
2187             badGrammarPhrase = TextCheckingHelper(*client(), *grammarSearchRange).findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);
2188 #endif
2189     }
2190     
2191     // If we found neither bad grammar nor a misspelled word, wrap and try again (but don't bother if we started at the beginning of the
2192     // block rather than at a selection).
2193     if (startedWithSelection && !misspelledWord && !badGrammarPhrase) {
2194         if (topNode)
2195             spellingSearchRange->setStart(*topNode, 0);
2196         // going until the end of the very first chunk we tested is far enough
2197         spellingSearchRange->setEnd(searchEndNodeAfterWrap, searchEndOffsetAfterWrap);
2198         
2199         if (unifiedTextCheckerEnabled()) {
2200             grammarSearchRange = spellingSearchRange->cloneRange();
2201             foundItem = TextCheckingHelper(*client(), spellingSearchRange).findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
2202             if (isSpelling) {
2203                 misspelledWord = foundItem;
2204                 misspellingOffset = foundOffset;
2205             } else {
2206                 badGrammarPhrase = foundItem;
2207                 grammarPhraseOffset = foundOffset;
2208             }
2209         } else {
2210             misspelledWord = TextCheckingHelper(*client(), spellingSearchRange).findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);
2211
2212 #if USE(GRAMMAR_CHECKING)
2213             grammarSearchRange = spellingSearchRange->cloneRange();
2214             if (!misspelledWord.isEmpty()) {
2215                 // Stop looking at start of next misspelled word
2216                 CharacterIterator chars(*grammarSearchRange);
2217                 chars.advance(misspellingOffset);
2218                 grammarSearchRange->setEnd(chars.range()->startContainer(), chars.range()->startOffset());
2219             }
2220
2221             if (isGrammarCheckingEnabled())
2222                 badGrammarPhrase = TextCheckingHelper(*client(), *grammarSearchRange).findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);
2223 #endif
2224         }
2225     }
2226     
2227 #if !USE(GRAMMAR_CHECKING)
2228     ASSERT(badGrammarPhrase.isEmpty());
2229     UNUSED_PARAM(grammarPhraseOffset);
2230 #else
2231     if (!badGrammarPhrase.isEmpty()) {
2232         // We found bad grammar. Since we only searched for bad grammar up to the first misspelled word, the bad grammar
2233         // takes precedence and we ignore any potential misspelled word. Select the grammar detail, update the spelling
2234         // panel, and store a marker so we draw the green squiggle later.
2235         
2236         ASSERT(badGrammarPhrase.length() > 0);
2237         ASSERT(grammarDetail.location != -1 && grammarDetail.length > 0);
2238         
2239         // FIXME 4859190: This gets confused with doubled punctuation at the end of a paragraph
2240         auto badGrammarRange = TextIterator::subrange(*grammarSearchRange, grammarPhraseOffset + grammarDetail.location, grammarDetail.length);
2241         m_frame.selection().setSelection(VisibleSelection(badGrammarRange, SEL_DEFAULT_AFFINITY));
2242         m_frame.selection().revealSelection();
2243         
2244         client()->updateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail);
2245         document().markers().addMarker(badGrammarRange, DocumentMarker::Grammar, grammarDetail.userDescription);
2246     } else
2247 #endif
2248     if (!misspelledWord.isEmpty()) {
2249         // We found a misspelling, but not any earlier bad grammar. Select the misspelling, update the spelling panel, and store
2250         // a marker so we draw the red squiggle later.
2251         
2252         auto misspellingRange = TextIterator::subrange(spellingSearchRange, misspellingOffset, misspelledWord.length());
2253         m_frame.selection().setSelection(VisibleSelection(misspellingRange, DOWNSTREAM));
2254         m_frame.selection().revealSelection();
2255         
2256         client()->updateSpellingUIWithMisspelledWord(misspelledWord);
2257         document().markers().addMarker(misspellingRange, DocumentMarker::Spelling);
2258     }
2259 }
2260
2261 #endif // !PLATFORM(IOS_FAMILY)
2262
2263 String Editor::misspelledWordAtCaretOrRange(Node* clickedNode) const
2264 {
2265     if (!isContinuousSpellCheckingEnabled() || !clickedNode || !isSpellCheckingEnabledFor(clickedNode))
2266         return String();
2267
2268     VisibleSelection selection = m_frame.selection().selection();
2269     if (!selection.isContentEditable() || selection.isNone())
2270         return String();
2271
2272     VisibleSelection wordSelection(selection.base());
2273     wordSelection.expandUsingGranularity(WordGranularity);
2274     RefPtr<Range> wordRange = wordSelection.toNormalizedRange();
2275     if (!wordRange)
2276         return String();
2277
2278     // In compliance with GTK+ applications, additionally allow to provide suggestions when the current
2279     // selection exactly match the word selection.
2280     if (selection.isRange() && !areRangesEqual(wordRange.get(), selection.toNormalizedRange().get()))
2281         return String();
2282
2283     String word = wordRange->text();
2284     if (word.isEmpty() || !client())
2285         return String();
2286
2287     int wordLength = word.length();
2288     int misspellingLocation = -1;
2289     int misspellingLength = 0;
2290     textChecker()->checkSpellingOfString(word, &misspellingLocation, &misspellingLength);
2291
2292     return misspellingLength == wordLength ? word : String();
2293 }
2294
2295 String Editor::misspelledSelectionString() const
2296 {
2297     String selectedString = selectedText();
2298     int length = selectedString.length();
2299     if (!length || !client())
2300         return String();
2301
2302     int misspellingLocation = -1;
2303     int misspellingLength = 0;
2304     textChecker()->checkSpellingOfString(selectedString, &misspellingLocation, &misspellingLength);
2305     
2306     // The selection only counts as misspelled if the selected text is exactly one misspelled word
2307     if (misspellingLength != length)
2308         return String();
2309     
2310     // Update the spelling panel to be displaying this error (whether or not the spelling panel is on screen).
2311     // This is necessary to make a subsequent call to [NSSpellChecker ignoreWord:inSpellDocumentWithTag:] work
2312     // correctly; that call behaves differently based on whether the spelling panel is displaying a misspelling
2313     // or a grammar error.
2314     client()->updateSpellingUIWithMisspelledWord(selectedString);
2315     
2316     return selectedString;
2317 }
2318
2319 bool Editor::isSelectionUngrammatical()
2320 {
2321 #if USE(GRAMMAR_CHECKING)
2322     RefPtr<Range> range = m_frame.selection().toNormalizedRange();
2323     if (!range || !client())
2324         return false;
2325     return TextCheckingHelper(*client(), *range).isUngrammatical();
2326 #else
2327     return false;
2328 #endif
2329 }
2330
2331 Vector<String> Editor::guessesForMisspelledWord(const String& word) const
2332 {
2333     ASSERT(word.length());
2334
2335     Vector<String> guesses;
2336     if (client())
2337         textChecker()->getGuessesForWord(word, String(), m_frame.selection().selection(), guesses);
2338     return guesses;
2339 }
2340
2341 Vector<String> Editor::guessesForMisspelledOrUngrammatical(bool& misspelled, bool& ungrammatical)
2342 {
2343     if (unifiedTextCheckerEnabled()) {
2344         RefPtr<Range> range;
2345         VisibleSelection selection = m_frame.selection().selection();
2346         if (selection.isCaret() && behavior().shouldAllowSpellingSuggestionsWithoutSelection()) {
2347             VisibleSelection wordSelection = VisibleSelection(selection.base());
2348             wordSelection.expandUsingGranularity(WordGranularity);
2349             range = wordSelection.toNormalizedRange();
2350         } else
2351             range = selection.toNormalizedRange();
2352         if (!range || !client())
2353             return Vector<String>();
2354         return TextCheckingHelper(*client(), *range).guessesForMisspelledOrUngrammaticalRange(isGrammarCheckingEnabled(), misspelled, ungrammatical);
2355     }
2356
2357     String misspelledWord = behavior().shouldAllowSpellingSuggestionsWithoutSelection() ? misspelledWordAtCaretOrRange(document().focusedElement()) : misspelledSelectionString();
2358     misspelled = !misspelledWord.isEmpty();
2359     // Only unified text checker supports guesses for ungrammatical phrases.
2360     ungrammatical = false;
2361
2362     if (misspelled)
2363         return guessesForMisspelledWord(misspelledWord);
2364     return Vector<String>();
2365 }
2366
2367 void Editor::showSpellingGuessPanel()
2368 {
2369     if (!client()) {
2370         LOG_ERROR("No NSSpellChecker");
2371         return;
2372     }
2373
2374     if (client()->spellingUIIsShowing()) {
2375         client()->showSpellingUI(false);
2376         return;
2377     }
2378
2379 #if !PLATFORM(IOS_FAMILY)
2380     advanceToNextMisspelling(true);
2381 #endif
2382     client()->showSpellingUI(true);
2383 }
2384
2385 bool Editor::spellingPanelIsShowing()
2386 {
2387     if (!client())
2388         return false;
2389     return client()->spellingUIIsShowing();
2390 }
2391
2392 void Editor::clearMisspellingsAndBadGrammar(const VisibleSelection& movingSelection)
2393 {
2394     if (auto selectedRange = movingSelection.toNormalizedRange())
2395         document().markers().removeMarkers(*selectedRange, { DocumentMarker::Spelling, DocumentMarker::Grammar });
2396 }
2397
2398 void Editor::markMisspellingsAndBadGrammar(const VisibleSelection &movingSelection)
2399 {
2400     markMisspellingsAndBadGrammar(movingSelection, isContinuousSpellCheckingEnabled() && isGrammarCheckingEnabled(), movingSelection);
2401 }
2402
2403 void Editor::markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart, const VisibleSelection& selectionAfterTyping, bool doReplacement)
2404 {
2405     Ref<Frame> protection(m_frame);
2406
2407     if (platformDrivenTextCheckerEnabled())
2408         return;
2409
2410 #if PLATFORM(IOS_FAMILY)
2411     UNUSED_PARAM(selectionAfterTyping);
2412     UNUSED_PARAM(doReplacement);
2413     OptionSet<TextCheckingType> textCheckingOptions;
2414     if (isContinuousSpellCheckingEnabled())
2415         textCheckingOptions.add(TextCheckingType::Spelling);
2416     if (!textCheckingOptions.contains(TextCheckingType::Spelling))
2417         return;
2418
2419     VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary));
2420     auto adjacentWordRange = adjacentWords.toNormalizedRange();
2421     markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWordRange.copyRef(), adjacentWordRange.copyRef(), adjacentWordRange.copyRef());
2422 #else
2423 #if !USE(AUTOMATIC_TEXT_REPLACEMENT)
2424     UNUSED_PARAM(doReplacement);
2425 #endif
2426
2427     if (unifiedTextCheckerEnabled()) {
2428         m_alternativeTextController->applyPendingCorrection(selectionAfterTyping);
2429
2430         OptionSet<TextCheckingType> textCheckingOptions;
2431
2432         if (isContinuousSpellCheckingEnabled())
2433             textCheckingOptions.add(TextCheckingType::Spelling);
2434
2435 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2436         if (doReplacement
2437             && (isAutomaticQuoteSubstitutionEnabled()
2438                 || isAutomaticLinkDetectionEnabled()
2439                 || isAutomaticDashSubstitutionEnabled()
2440                 || isAutomaticTextReplacementEnabled()
2441                 || (textCheckingOptions.contains(TextCheckingType::Spelling) && isAutomaticSpellingCorrectionEnabled())))
2442             textCheckingOptions.add(TextCheckingType::Replacement);
2443 #endif
2444         if (!textCheckingOptions.contains(TextCheckingType::Spelling) && !textCheckingOptions.contains(TextCheckingType::Replacement))
2445             return;
2446
2447         if (isGrammarCheckingEnabled())
2448             textCheckingOptions.add(TextCheckingType::Grammar);
2449
2450         auto sentenceStart = startOfSentence(wordStart);
2451         auto sentenceEnd = endOfSentence(wordStart);
2452         VisibleSelection fullSentence(sentenceStart, sentenceEnd);
2453         auto fullSentenceRange = fullSentence.toNormalizedRange();
2454         if (!fullSentenceRange)
2455             return;
2456
2457         auto spellCheckingStart = wordStart;
2458         auto spellCheckingEnd = wordStart;
2459
2460         // FIXME: The following logic doesn't handle adding spelling markers due to retro sentence corrections when an
2461         // incorrectly spelled range is separated from the start of the current word by a text node inside an element
2462         // with spellcheck disabled. To fix this, we need to refactor markAllMisspellingsAndBadGrammarInRanges so that
2463         // it can handle a list of spelling ranges, alongside the grammar range.
2464         while (sentenceStart < spellCheckingStart) {
2465             auto previousPosition = spellCheckingStart.previous(CannotCrossEditingBoundary);
2466             if (previousPosition.isNull() || previousPosition == spellCheckingStart)
2467                 break;
2468
2469             auto* container = previousPosition.deepEquivalent().downstream().containerNode();
2470             if (auto* containerElement = is<Element>(container) ? downcast<Element>(container) : container->parentElement()) {
2471                 if (!containerElement->isSpellCheckingEnabled())
2472                     break;
2473             }
2474
2475             spellCheckingStart = previousPosition;
2476         }
2477
2478         while (spellCheckingEnd < sentenceEnd) {
2479             auto nextPosition = spellCheckingEnd.next(CannotCrossEditingBoundary);
2480             if (nextPosition.isNull() || nextPosition == spellCheckingEnd)
2481                 break;
2482
2483             auto* container = nextPosition.deepEquivalent().upstream().containerNode();
2484             if (auto* containerElement = is<Element>(container) ? downcast<Element>(container) : container->parentElement()) {
2485                 if (!containerElement->isSpellCheckingEnabled())
2486                     break;
2487             }
2488
2489             spellCheckingEnd = nextPosition;
2490         }
2491
2492         auto spellCheckingRange = VisibleSelection(spellCheckingStart, spellCheckingEnd).toNormalizedRange();
2493         if (!spellCheckingRange)
2494             return;
2495
2496         auto adjacentWordRange = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)).toNormalizedRange();
2497         if (!adjacentWordRange)
2498             return;
2499
2500         // The spelling and grammar markers in these ranges are recomputed. This is because typing a word may
2501         // cause any other part of the current sentence to lose or gain spelling correction markers, due to
2502         // sentence retro correction. As such, we expand the spell checking range to encompass as much of the
2503         // full sentence as we can, respecting boundaries where spellchecking is disabled.
2504         fullSentenceRange->ownerDocument().markers().removeMarkers(*fullSentenceRange, DocumentMarker::Grammar);
2505         spellCheckingRange->ownerDocument().markers().removeMarkers(*spellCheckingRange, DocumentMarker::Spelling);
2506         markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, WTFMove(spellCheckingRange), WTFMove(adjacentWordRange), WTFMove(fullSentenceRange));
2507         return;
2508     }
2509
2510     if (!isContinuousSpellCheckingEnabled())
2511         return;
2512
2513     // Check spelling of one word
2514     RefPtr<Range> misspellingRange;
2515     markMisspellings(VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)), misspellingRange);
2516
2517     // Autocorrect the misspelled word.
2518     if (!misspellingRange)
2519         return;
2520     
2521     // Get the misspelled word.
2522     const String misspelledWord = plainText(misspellingRange.get());
2523     String autocorrectedString = textChecker()->getAutoCorrectSuggestionForMisspelledWord(misspelledWord);
2524
2525     // If autocorrected word is non empty, replace the misspelled word by this word.
2526     if (!autocorrectedString.isEmpty()) {
2527         VisibleSelection newSelection(*misspellingRange, DOWNSTREAM);
2528         if (newSelection != m_frame.selection().selection()) {
2529             if (!m_frame.selection().shouldChangeSelection(newSelection))
2530                 return;
2531             m_frame.selection().setSelection(newSelection);
2532         }
2533
2534         if (!m_frame.editor().shouldInsertText(autocorrectedString, misspellingRange.get(), EditorInsertAction::Typed))
2535             return;
2536         m_frame.editor().replaceSelectionWithText(autocorrectedString, SelectReplacement::No, SmartReplace::No, EditAction::Insert);
2537
2538         // Reset the charet one character further.
2539         m_frame.selection().moveTo(m_frame.selection().selection().end());
2540         m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
2541     }
2542
2543     if (!isGrammarCheckingEnabled())
2544         return;
2545     
2546     // Check grammar of entire sentence
2547     markBadGrammar(VisibleSelection(startOfSentence(wordStart), endOfSentence(wordStart)));
2548 #endif
2549 }
2550     
2551 void Editor::markMisspellingsOrBadGrammar(const VisibleSelection& selection, bool checkSpelling, RefPtr<Range>& firstMisspellingRange)
2552 {
2553 #if !PLATFORM(IOS_FAMILY)
2554     // This function is called with a selection already expanded to word boundaries.
2555     // Might be nice to assert that here.
2556     
2557     // This function is used only for as-you-type checking, so if that's off we do nothing. Note that
2558     // grammar checking can only be on if spell checking is also on.
2559     if (!isContinuousSpellCheckingEnabled())
2560         return;
2561     
2562     RefPtr<Range> searchRange(selection.toNormalizedRange());
2563     if (!searchRange)
2564         return;
2565     
2566     // If we're not in an editable node, bail.
2567     Node& editableNode = searchRange->startContainer();
2568     if (!editableNode.hasEditableStyle())
2569         return;
2570
2571     if (!isSpellCheckingEnabledFor(&editableNode))
2572         return;
2573
2574     // Get the spell checker if it is available
2575     if (!client())
2576         return;
2577     
2578     TextCheckingHelper checker(*client(), *searchRange);
2579     if (checkSpelling)
2580         checker.markAllMisspellings(firstMisspellingRange);
2581     else {
2582 #if USE(GRAMMAR_CHECKING)
2583         if (isGrammarCheckingEnabled())
2584             checker.markAllBadGrammar();
2585 #else
2586         ASSERT_NOT_REACHED();
2587 #endif
2588     }    
2589 #else
2590         UNUSED_PARAM(selection);
2591         UNUSED_PARAM(checkSpelling);
2592         UNUSED_PARAM(firstMisspellingRange);
2593 #endif // !PLATFORM(IOS_FAMILY)
2594 }
2595
2596 bool Editor::isSpellCheckingEnabledFor(Node* node) const
2597 {
2598     if (!node)
2599         return false;
2600     Element* element = is<Element>(*node) ? downcast<Element>(node) : node->parentElement();
2601     if (!element)
2602         return false;
2603     if (element->isInUserAgentShadowTree()) {
2604         if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(firstPositionInOrBeforeNode(element)))
2605             return textControl->isSpellCheckingEnabled();
2606     }
2607     return element->isSpellCheckingEnabled();
2608 }
2609
2610 bool Editor::isSpellCheckingEnabledInFocusedNode() const
2611 {
2612     return isSpellCheckingEnabledFor(m_frame.selection().selection().start().deprecatedNode());
2613 }
2614
2615 void Editor::markMisspellings(const VisibleSelection& selection, RefPtr<Range>& firstMisspellingRange)
2616 {
2617     markMisspellingsOrBadGrammar(selection, true, firstMisspellingRange);
2618 }
2619     
2620 void Editor::markBadGrammar(const VisibleSelection& selection)
2621 {
2622 #if USE(GRAMMAR_CHECKING)
2623     RefPtr<Range> firstMisspellingRange;
2624     markMisspellingsOrBadGrammar(selection, false, firstMisspellingRange);
2625 #else
2626     ASSERT_NOT_REACHED();
2627 #endif
2628 }
2629
2630 void Editor::markAllMisspellingsAndBadGrammarInRanges(OptionSet<TextCheckingType> textCheckingOptions, RefPtr<Range>&& spellingRange, RefPtr<Range>&& automaticReplacementRange, RefPtr<Range>&& grammarRange)
2631 {
2632     if (platformDrivenTextCheckerEnabled())
2633         return;
2634
2635     ASSERT(unifiedTextCheckerEnabled());
2636
2637     // There shouldn't be pending autocorrection at this moment.
2638     ASSERT(!m_alternativeTextController->hasPendingCorrection());
2639
2640     bool shouldMarkGrammar = textCheckingOptions.contains(TextCheckingType::Grammar);
2641     bool shouldShowCorrectionPanel = textCheckingOptions.contains(TextCheckingType::ShowCorrectionPanel);
2642
2643     // This function is called with selections already expanded to word boundaries.
2644     if (!client() || !spellingRange || (shouldMarkGrammar && !grammarRange))
2645         return;
2646
2647     // If we're not in an editable node, bail.
2648     Node& editableNode = spellingRange->startContainer();
2649     if (!editableNode.hasEditableStyle())
2650         return;
2651
2652     if (!isSpellCheckingEnabledFor(&editableNode))
2653         return;
2654
2655     auto rangeToCheck = shouldMarkGrammar ? grammarRange.releaseNonNull() : spellingRange.releaseNonNull();
2656     TextCheckingParagraph paragraphToCheck(rangeToCheck.get());
2657     if (paragraphToCheck.isEmpty())
2658         return;
2659
2660     bool asynchronous = m_frame.settings().asynchronousSpellCheckingEnabled() && !shouldShowCorrectionPanel;
2661
2662     // In asynchronous mode, we intentionally check paragraph-wide sentence.
2663     const auto resolvedOptions = resolveTextCheckingTypeMask(editableNode, textCheckingOptions);
2664     auto textReplacementRange = automaticReplacementRange ? makeRef(*automaticReplacementRange) : rangeToCheck.copyRef();
2665     auto request = SpellCheckRequest::create(resolvedOptions, TextCheckingProcessIncremental, asynchronous ? makeRef(paragraphToCheck.paragraphRange()) : WTFMove(rangeToCheck), WTFMove(textReplacementRange), paragraphToCheck.paragraphRange());
2666     if (!request)
2667         return;
2668
2669     if (asynchronous) {
2670         m_spellChecker->requestCheckingFor(request.releaseNonNull());
2671         return;
2672     }
2673
2674     Vector<TextCheckingResult> results;
2675     checkTextOfParagraph(*textChecker(), paragraphToCheck.text(), resolvedOptions, results, m_frame.selection().selection());
2676     markAndReplaceFor(request.releaseNonNull(), results);
2677 }
2678
2679 static bool isAutomaticTextReplacementType(TextCheckingType type)
2680 {
2681     switch (type) {
2682     case TextCheckingType::None:
2683     case TextCheckingType::Spelling:
2684     case TextCheckingType::Grammar:
2685         return false;
2686     case TextCheckingType::Link:
2687     case TextCheckingType::Quote:
2688     case TextCheckingType::Dash:
2689     case TextCheckingType::Replacement:
2690     case TextCheckingType::Correction:
2691     case TextCheckingType::ShowCorrectionPanel:
2692         return true;
2693     }
2694     ASSERT_NOT_REACHED();
2695     return false;
2696 }
2697
2698 void Editor::replaceRangeForSpellChecking(Range& rangeToReplace, const String& replacement)
2699 {
2700     SpellingCorrectionCommand::create(rangeToReplace, replacement)->apply();
2701 }
2702
2703 static void correctSpellcheckingPreservingTextCheckingParagraph(TextCheckingParagraph& paragraph, Range& rangeToReplace, const String& replacement, int resultLocation, int resultLength)
2704 {
2705     auto& scope = downcast<ContainerNode>(paragraph.paragraphRange().startContainer().rootNode());
2706
2707     size_t paragraphLocation;
2708     size_t paragraphLength;
2709     TextIterator::getLocationAndLengthFromRange(&scope, &paragraph.paragraphRange(), paragraphLocation, paragraphLength);
2710
2711     SpellingCorrectionCommand::create(rangeToReplace, replacement)->apply();
2712
2713     // TextCheckingParagraph may be orphaned after SpellingCorrectionCommand mutated DOM.
2714     // See <rdar://10305315>, http://webkit.org/b/89526.
2715
2716     RefPtr<Range> newParagraphRange = TextIterator::rangeFromLocationAndLength(&scope, paragraphLocation, paragraphLength + replacement.length() - resultLength);
2717
2718     auto spellCheckingRange = TextIterator::subrange(*newParagraphRange, resultLocation, replacement.length());
2719     paragraph = TextCheckingParagraph(spellCheckingRange.copyRef(), spellCheckingRange.copyRef(), newParagraphRange.get());
2720 }
2721
2722 void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<TextCheckingResult>& results)
2723 {
2724     Ref<Frame> protection(m_frame);
2725
2726     auto textCheckingOptions = request.data().checkingTypes();
2727     TextCheckingParagraph paragraph(request.checkingRange(), request.automaticReplacementRange(), &request.paragraphRange());
2728
2729     // FIXME: Mark this const once MSVC bug is fixed: <https://developercommunity.visualstudio.com/content/problem/316713/msvc-cant-compile-webkits-optionsetcontainsany.html>.
2730     bool shouldPerformReplacement = textCheckingOptions.containsAny({ TextCheckingType::Quote, TextCheckingType::Dash, TextCheckingType::Replacement });
2731     const bool shouldMarkSpelling = textCheckingOptions.contains(TextCheckingType::Spelling);
2732     const bool shouldMarkGrammar = textCheckingOptions.contains(TextCheckingType::Grammar);
2733     const bool shouldMarkLink = textCheckingOptions.contains(TextCheckingType::Link);
2734     const bool shouldShowCorrectionPanel = textCheckingOptions.contains(TextCheckingType::ShowCorrectionPanel);
2735     const bool shouldCheckForCorrection = shouldShowCorrectionPanel || textCheckingOptions.contains(TextCheckingType::Correction);
2736 #if !USE(AUTOCORRECTION_PANEL)
2737     ASSERT(!shouldShowCorrectionPanel);
2738 #endif
2739
2740     // Expand the range to encompass entire paragraphs, since text checking needs that much context.
2741     int selectionOffset = 0;
2742     bool useAmbiguousBoundaryOffset = false;
2743     bool selectionChanged = false;
2744     bool restoreSelectionAfterChange = false;
2745     bool adjustSelectionForParagraphBoundaries = false;
2746
2747     if (shouldPerformReplacement || shouldMarkSpelling || shouldCheckForCorrection) {
2748         if (m_frame.selection().selection().selectionType() == VisibleSelection::CaretSelection) {
2749             // Attempt to save the caret position so we can restore it later if needed
2750             Position caretPosition = m_frame.selection().selection().end();
2751             selectionOffset = paragraph.offsetTo(caretPosition).releaseReturnValue();
2752             restoreSelectionAfterChange = true;
2753             if (selectionOffset > 0 && (selectionOffset > paragraph.textLength() || paragraph.textCharAt(selectionOffset - 1) == newlineCharacter))
2754                 adjustSelectionForParagraphBoundaries = true;
2755             if (selectionOffset > 0 && selectionOffset <= paragraph.textLength() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(selectionOffset - 1)))
2756                 useAmbiguousBoundaryOffset = true;
2757         }
2758     }
2759
2760     int offsetDueToReplacement = 0;
2761
2762     for (unsigned i = 0; i < results.size(); i++) {
2763         const int spellingRangeEndOffset = paragraph.checkingEnd() + offsetDueToReplacement;
2764         const TextCheckingType resultType = results[i].type;
2765         const int resultLocation = results[i].location + offsetDueToReplacement;
2766         const int resultLength = results[i].length;
2767         const int resultEndLocation = resultLocation + resultLength;
2768         const int automaticReplacementEndLocation = paragraph.automaticReplacementStart() + paragraph.automaticReplacementLength() + offsetDueToReplacement;
2769         const String& replacement = results[i].replacement;
2770         const bool resultEndsAtAmbiguousBoundary = useAmbiguousBoundaryOffset && selectionOffset - 1 <= resultEndLocation;
2771
2772         // Only mark misspelling if:
2773         // 1. Current text checking isn't done for autocorrection, in which case shouldMarkSpelling is false.
2774         // 2. Result falls within spellingRange.
2775         // 3. The word in question doesn't end at an ambiguous boundary. For instance, we would not mark
2776         //    "wouldn'" as misspelled right after apostrophe is typed.
2777         if (shouldMarkSpelling && !shouldShowCorrectionPanel && resultType == TextCheckingType::Spelling
2778             && resultLocation >= paragraph.checkingStart() && resultEndLocation <= spellingRangeEndOffset && !resultEndsAtAmbiguousBoundary) {
2779             ASSERT(resultLength > 0 && resultLocation >= 0);
2780             auto misspellingRange = paragraph.subrange(resultLocation, resultLength);
2781             if (!m_alternativeTextController->isSpellingMarkerAllowed(misspellingRange))
2782                 continue;
2783             misspellingRange->startContainer().document().markers().addMarker(misspellingRange, DocumentMarker::Spelling, replacement);
2784         } else if (shouldMarkGrammar && resultType == TextCheckingType::Grammar && paragraph.checkingRangeCovers(resultLocation, resultLength)) {
2785             ASSERT(resultLength > 0 && resultLocation >= 0);
2786             for (auto& detail : results[i].details) {
2787                 ASSERT(detail.length > 0 && detail.location >= 0);
2788                 if (paragraph.checkingRangeCovers(resultLocation + detail.location, detail.length)) {
2789                     auto badGrammarRange = paragraph.subrange(resultLocation + detail.location, detail.length);
2790                     badGrammarRange->startContainer().document().markers().addMarker(badGrammarRange, DocumentMarker::Grammar, detail.userDescription);
2791                 }
2792             }
2793         } else if (resultEndLocation <= automaticReplacementEndLocation && resultEndLocation >= paragraph.automaticReplacementStart()
2794             && isAutomaticTextReplacementType(resultType)) {
2795             // In this case the result range just has to touch the automatic replacement range, so we can handle replacing non-word text such as punctuation.
2796             ASSERT(resultLength > 0 && resultLocation >= 0);
2797
2798             if (shouldShowCorrectionPanel && (resultEndLocation < automaticReplacementEndLocation
2799                 || (resultType != TextCheckingType::Replacement && resultType != TextCheckingType::Correction)))
2800                 continue;
2801
2802             // Apply replacement if:
2803             // 1. The replacement length is non-zero.
2804             // 2. The result doesn't end at an ambiguous boundary.
2805             //    (FIXME: this is required until 6853027 is fixed and text checking can do this for us
2806             bool doReplacement = replacement.length() > 0 && !resultEndsAtAmbiguousBoundary;
2807             auto rangeToReplace = paragraph.subrange(resultLocation, resultLength);
2808
2809             // Adding links should be done only immediately after they are typed.
2810             if (resultType == TextCheckingType::Link && selectionOffset != resultEndLocation + 1)
2811                 continue;
2812
2813             if (!(shouldPerformReplacement || shouldCheckForCorrection || shouldMarkLink) || !doReplacement)
2814                 continue;
2815
2816             String replacedString = plainText(rangeToReplace.ptr());
2817             const bool existingMarkersPermitReplacement = m_alternativeTextController->processMarkersOnTextToBeReplacedByResult(results[i], rangeToReplace, replacedString);
2818             if (!existingMarkersPermitReplacement)
2819                 continue;
2820
2821             if (shouldShowCorrectionPanel) {
2822                 if (resultEndLocation == automaticReplacementEndLocation) {
2823                     // We only show the correction panel on the last word.
2824                     m_alternativeTextController->show(rangeToReplace, replacement);
2825                     break;
2826                 }
2827                 // If this function is called for showing correction panel, we ignore other correction or replacement.
2828                 continue;
2829             }
2830
2831             VisibleSelection selectionToReplace(rangeToReplace, DOWNSTREAM);
2832             if (selectionToReplace != m_frame.selection().selection()) {
2833                 if (!m_frame.selection().shouldChangeSelection(selectionToReplace))
2834                     continue;
2835             }
2836
2837             if (resultType == TextCheckingType::Link) {
2838                 m_frame.selection().setSelection(selectionToReplace);
2839                 selectionChanged = true;
2840                 restoreSelectionAfterChange = false;
2841                 if (canEditRichly())
2842                     CreateLinkCommand::create(document(), replacement)->apply();
2843             } else if (canEdit() && shouldInsertText(replacement, rangeToReplace.ptr(), EditorInsertAction::Typed)) {
2844                 correctSpellcheckingPreservingTextCheckingParagraph(paragraph, rangeToReplace, replacement, resultLocation, resultLength);
2845
2846                 if (AXObjectCache* cache = document().existingAXObjectCache()) {
2847                     if (Element* root = m_frame.selection().selection().rootEditableElement())
2848                         cache->postNotification(root, AXObjectCache::AXAutocorrectionOccured);
2849                 }
2850
2851                 // Skip all other results for the replaced text.
2852                 while (i + 1 < results.size() && results[i + 1].location + offsetDueToReplacement <= resultLocation)
2853                     i++;
2854
2855                 selectionChanged = true;
2856                 offsetDueToReplacement += replacement.length() - resultLength;
2857                 if (resultLocation < selectionOffset)
2858                     selectionOffset += replacement.length() - resultLength;
2859
2860                 if (resultType == TextCheckingType::Correction) {
2861                     auto replacementRange = paragraph.subrange(resultLocation, replacement.length());
2862                     m_alternativeTextController->recordAutocorrectionResponse(AutocorrectionResponse::Accepted, replacedString, replacementRange.ptr());
2863
2864                     // Add a marker so that corrections can easily be undone and won't be re-corrected.
2865                     m_alternativeTextController->markCorrection(replacementRange, replacedString);
2866                 }
2867             }
2868         }
2869     }
2870
2871     if (selectionChanged) {
2872         TextCheckingParagraph extendedParagraph(WTFMove(paragraph));
2873         // Restore the caret position if we have made any replacements
2874         extendedParagraph.expandRangeToNextEnd();
2875         if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffset <= extendedParagraph.rangeLength()) {
2876             auto selectionRange = extendedParagraph.subrange(0, selectionOffset);
2877             m_frame.selection().moveTo(selectionRange->endPosition(), DOWNSTREAM);
2878             if (adjustSelectionForParagraphBoundaries)
2879                 m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
2880         } else {
2881             // If this fails for any reason, the fallback is to go one position beyond the last replacement
2882             m_frame.selection().moveTo(m_frame.selection().selection().end());
2883             m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
2884         }
2885     }
2886 }
2887
2888 void Editor::changeBackToReplacedString(const String& replacedString)
2889 {
2890 #if !PLATFORM(IOS_FAMILY)
2891     ASSERT(unifiedTextCheckerEnabled());
2892
2893     if (replacedString.isEmpty())
2894         return;
2895
2896     RefPtr<Range> selection = selectedRange();
2897     if (!shouldInsertText(replacedString, selection.get(), EditorInsertAction::Pasted))
2898         return;
2899     
2900     m_alternativeTextController->recordAutocorrectionResponse(AutocorrectionResponse::Reverted, replacedString, selection.get());
2901     TextCheckingParagraph paragraph(*selection);
2902     replaceSelectionWithText(replacedString, SelectReplacement::No, SmartReplace::No, EditAction::Insert);
2903     auto changedRange = paragraph.subrange(paragraph.checkingStart(), replacedString.length());
2904     changedRange->startContainer().document().markers().addMarker(changedRange, DocumentMarker::Replacement, String());
2905     m_alternativeTextController->markReversed(changedRange);
2906 #else
2907     ASSERT_NOT_REACHED();
2908     UNUSED_PARAM(replacedString);
2909 #endif // !PLATFORM(IOS_FAMILY)
2910 }
2911
2912
2913 void Editor::markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelection, bool markGrammar, const VisibleSelection& grammarSelection)
2914 {
2915     if (platformDrivenTextCheckerEnabled())
2916         return;
2917
2918     if (unifiedTextCheckerEnabled()) {
2919         if (!isContinuousSpellCheckingEnabled())
2920             return;
2921
2922         // markMisspellingsAndBadGrammar() is triggered by selection change, in which case we check spelling and grammar, but don't autocorrect misspellings.
2923         OptionSet<TextCheckingType> textCheckingOptions { TextCheckingType::Spelling };
2924         if (markGrammar && isGrammarCheckingEnabled())
2925             textCheckingOptions.add(TextCheckingType::Grammar);
2926         auto spellCheckingRange = spellingSelection.toNormalizedRange();
2927         markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, spellCheckingRange.copyRef(), spellCheckingRange.copyRef(), grammarSelection.toNormalizedRange());
2928         return;
2929     }
2930
2931     RefPtr<Range> firstMisspellingRange;
2932     markMisspellings(spellingSelection, firstMisspellingRange);
2933     if (markGrammar)
2934         markBadGrammar(grammarSelection);
2935 }
2936
2937 void Editor::unappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction)
2938 {
2939     m_alternativeTextController->respondToUnappliedSpellCorrection(selectionOfCorrected, corrected, correction);
2940 }
2941
2942 void Editor::updateMarkersForWordsAffectedByEditing(bool doNotRemoveIfSelectionAtWordBoundary)
2943 {
2944     if (!document().markers().hasMarkers())
2945         return;
2946
2947     if (!m_alternativeTextController->shouldRemoveMarkersUponEditing() && (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingType::Spelling)))
2948         return;
2949
2950     // We want to remove the markers from a word if an editing command will change the word. This can happen in one of
2951     // several scenarios:
2952     // 1. Insert in the middle of a word.
2953     // 2. Appending non whitespace at the beginning of word.
2954     // 3. Appending non whitespace at the end of word.
2955     // Note that, appending only whitespaces at the beginning or end of word won't change the word, so we don't need to
2956     // remove the markers on that word.
2957     // Of course, if current selection is a range, we potentially will edit two words that fall on the boundaries of
2958     // selection, and remove words between the selection boundaries.
2959     //
2960     VisiblePosition startOfSelection = m_frame.selection().selection().start();
2961     VisiblePosition endOfSelection = m_frame.selection().selection().end();
2962     if (startOfSelection.isNull())
2963         return;
2964     // First word is the word that ends after or on the start of selection.
2965     VisiblePosition startOfFirstWord = startOfWord(startOfSelection, LeftWordIfOnBoundary);
2966     VisiblePosition endOfFirstWord = endOfWord(startOfSelection, LeftWordIfOnBoundary);
2967     // Last word is the word that begins before or on the end of selection
2968     VisiblePosition startOfLastWord = startOfWord(endOfSelection, RightWordIfOnBoundary);
2969     VisiblePosition endOfLastWord = endOfWord(endOfSelection, RightWordIfOnBoundary);
2970
2971     if (startOfFirstWord.isNull()) {
2972         startOfFirstWord = startOfWord(startOfSelection, RightWordIfOnBoundary);
2973         endOfFirstWord = endOfWord(startOfSelection, RightWordIfOnBoundary);
2974     }
2975     
2976     if (endOfLastWord.isNull()) {
2977         startOfLastWord = startOfWord(endOfSelection, LeftWordIfOnBoundary);
2978         endOfLastWord = endOfWord(endOfSelection, LeftWordIfOnBoundary);
2979     }
2980
2981     // If doNotRemoveIfSelectionAtWordBoundary is true, and first word ends at the start of selection,
2982     // we choose next word as the first word.
2983     if (doNotRemoveIfSelectionAtWordBoundary && endOfFirstWord == startOfSelection) {
2984         startOfFirstWord = nextWordPosition(startOfFirstWord);
2985         endOfFirstWord = endOfWord(startOfFirstWord, RightWordIfOnBoundary);
2986         if (startOfFirstWord == endOfSelection)
2987             return;
2988     }
2989
2990     // If doNotRemoveIfSelectionAtWordBoundary is true, and last word begins at the end of selection,
2991     // we choose previous word as the last word.
2992     if (doNotRemoveIfSelectionAtWordBoundary && startOfLastWord == endOfSelection) {
2993         startOfLastWord = previousWordPosition(startOfLastWord);
2994         endOfLastWord = endOfWord(startOfLastWord, RightWordIfOnBoundary);
2995         if (endOfLastWord == startOfSelection)
2996             return;
2997     }
2998
2999     if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord.isNull() || endOfLastWord.isNull())
3000         return;
3001
3002     // Now we remove markers on everything between startOfFirstWord and endOfLastWord.
3003     // However, if an autocorrection change a single word to multiple words, we want to remove correction mark from all the
3004     // resulted words even we only edit one of them. For example, assuming autocorrection changes "avantgarde" to "avant
3005     // garde", we will have CorrectionIndicator marker on both words and on the whitespace between them. If we then edit garde,
3006     // we would like to remove the marker from word "avant" and whitespace as well. So we need to get the continous range of
3007     // of marker that contains the word in question, and remove marker on that whole range.
3008     auto wordRange = Range::create(document(), startOfFirstWord.deepEquivalent(), endOfLastWord.deepEquivalent());
3009
3010     Vector<RenderedDocumentMarker*> markers = document().markers().markersInRange(wordRange, DocumentMarker::DictationAlternatives);
3011     for (auto* marker : markers)
3012         m_alternativeTextController->removeDictationAlternativesForMarker(*marker);
3013
3014     OptionSet<DocumentMarker::MarkerType> markerTypesToRemove {
3015         DocumentMarker::CorrectionIndicator,
3016         DocumentMarker::DictationAlternatives,
3017         DocumentMarker::SpellCheckingExemption,
3018         DocumentMarker::Spelling,
3019 #if !PLATFORM(IOS_FAMILY)
3020         DocumentMarker::Grammar,
3021 #endif
3022     };
3023     document().markers().removeMarkers(wordRange, markerTypesToRemove, DocumentMarkerController::RemovePartiallyOverlappingMarker);
3024     document().markers().clearDescriptionOnMarkersIntersectingRange(wordRange, DocumentMarker::Replacement);
3025 }
3026
3027 void Editor::deletedAutocorrectionAtPosition(const Position& position, const String& originalString)
3028 {
3029     m_alternativeTextController->deletedAutocorrectionAtPosition(position, originalString);
3030 }
3031
3032 RefPtr<Range> Editor::rangeForPoint(const IntPoint& windowPoint)
3033 {
3034     Document* document = m_frame.documentAtPoint(windowPoint);
3035     if (!document)
3036         return nullptr;
3037     
3038     Frame* frame = document->frame();
3039     ASSERT(frame);
3040     FrameView* frameView = frame->view();
3041     if (!frameView)
3042         return nullptr;
3043     IntPoint framePoint = frameView->windowToContents(windowPoint);
3044     VisibleSelection selection(frame->visiblePositionForPoint(framePoint));
3045
3046     return selection.toNormalizedRange();
3047 }
3048
3049 void Editor::revealSelectionAfterEditingOperation(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
3050 {
3051     if (m_ignoreSelectionChanges)
3052         return;
3053
3054     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
3055     m_frame.selection().revealSelection(revealMode, alignment, revealExtentOption);
3056 }
3057
3058 void Editor::setIgnoreSelectionChanges(bool ignore, RevealSelection shouldRevealExistingSelection)
3059 {
3060     if (m_ignoreSelectionChanges == ignore)
3061         return;
3062
3063     m_ignoreSelectionChanges = ignore;
3064 #if PLATFORM(IOS_FAMILY)
3065     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830> 
3066     if (!ignore)
3067         respondToChangedSelection(m_frame.selection().selection(), { });
3068 #endif
3069     if (!ignore && shouldRevealExistingSelection == RevealSelection::Yes)
3070         revealSelectionAfterEditingOperation(ScrollAlignment::alignToEdgeIfNeeded, RevealExtent);
3071 }
3072
3073 RefPtr<Range> Editor::compositionRange() const
3074 {
3075     if (!m_compositionNode)
3076         return nullptr;
3077     unsigned length = m_compositionNode->length();
3078     unsigned start = std::min(m_compositionStart, length);
3079     unsigned end = std::min(std::max(start, m_compositionEnd), length);
3080     if (start >= end)
3081         return nullptr;
3082     return Range::create(m_compositionNode->document(), m_compositionNode.get(), start, m_compositionNode.get(), end);
3083 }
3084
3085 bool Editor::getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const
3086 {
3087     if (!m_compositionNode)
3088         return false;
3089     const VisibleSelection& selection = m_frame.selection().selection();
3090     Position start = selection.start();
3091     if (start.deprecatedNode() != m_compositionNode)
3092         return false;
3093     Position end = selection.end();
3094     if (end.deprecatedNode() != m_compositionNode)
3095         return false;
3096
3097     if (static_cast<unsigned>(start.deprecatedEditingOffset()) < m_compositionStart)
3098         return false;
3099     if (static_cast<unsigned>(end.deprecatedEditingOffset()) > m_compositionEnd)
3100         return false;
3101
3102     selectionStart = start.deprecatedEditingOffset() - m_compositionStart;
3103     selectionEnd = start.deprecatedEditingOffset() - m_compositionEnd;
3104     return true;
3105 }
3106
3107 void Editor::transpose()
3108 {
3109     if (!canEdit())
3110         return;
3111
3112     VisibleSelection selection = m_frame.selection().selection();
3113     if (!selection.isCaret())
3114         return;
3115
3116     // Make a selection that goes back one character and forward two characters.
3117     VisiblePosition caret = selection.visibleStart();
3118     VisiblePosition next = isEndOfParagraph(caret) ? caret : caret.next();
3119     VisiblePosition previous = next.previous();
3120     if (next == previous)
3121         return;
3122     previous = previous.previous();
3123     if (!inSameParagraph(next, previous))
3124         return;
3125     RefPtr<Range> range = makeRange(previous, next);
3126     if (!range)
3127         return;
3128     VisibleSelection newSelection(*range, DOWNSTREAM);
3129
3130     // Transpose the two characters.
3131     String text = plainText(range.get());
3132     if (text.length() != 2)
3133         return;
3134     String transposed = text.right(1) + text.left(1);
3135
3136     // Select the two characters.
3137     if (newSelection != m_frame.selection().selection()) {
3138         if (!m_frame.selection().shouldChangeSelection(newSelection))
3139             return;
3140         m_frame.selection().setSelection(newSelection);
3141     }
3142
3143     // Insert the transposed characters.
3144     if (!shouldInsertText(transposed, range.get(), EditorInsertAction::Typed))
3145         return;
3146     replaceSelectionWithText(transposed, SelectReplacement::No, SmartReplace::No, EditAction::Insert);
3147 }
3148
3149 void Editor::addRangeToKillRing(const Range& range, KillRingInsertionMode mode)
3150 {
3151     addTextToKillRing(plainText(&range), mode);
3152 }
3153
3154 void Editor::addTextToKillRing(const String& text, KillRingInsertionMode mode)
3155 {
3156     if (m_shouldStartNewKillRingSequence)
3157         killRing().startNewSequence();
3158
3159     m_shouldStartNewKillRingSequence = false;
3160
3161     // If the kill was from a backwards motion, prepend to the kill ring.
3162     // This will ensure that alternating forward and backward kills will
3163     // build up the original string in the kill ring without permuting it.
3164     switch (mode) {
3165     case KillRingInsertionMode::PrependText:
3166         killRing().prepend(text);
3167         break;
3168     case KillRingInsertionMode::AppendText:
3169         killRing().append(text);
3170         break;
3171     }
3172 }
3173
3174 void Editor::startAlternativeTextUITimer()
3175 {
3176     m_alternativeTextController->startAlternativeTextUITimer(AlternativeTextTypeCorrection);
3177 }
3178
3179 void Editor::handleAlternativeTextUIResult(const String& correction)
3180 {
3181     m_alternativeTextController->handleAlternativeTextUIResult(correction);
3182 }
3183
3184
3185 void Editor::dismissCorrectionPanelAsIgnored()
3186 {
3187     m_alternativeTextController->dismiss(ReasonForDismissingAlternativeTextIgnored);
3188 }
3189
3190 void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection, OptionSet<FrameSelection::SetSelectionOption> options)
3191 {
3192     Ref<Frame> protection(m_frame);
3193
3194     // If the new selection is orphaned, then don't update the selection.
3195     if (newSelection.start().isOrphan() || newSelection.end().isOrphan())
3196         return;
3197
3198     // If there is no selection change, don't bother sending shouldChangeSelection, but still call setSelection,
3199     // because there is work that it must do in this situation.
3200     // The old selection can be invalid here and calling shouldChangeSelection can produce some strange calls.
3201     // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ranges for selections that are no longer valid
3202     bool selectionDidNotChangeDOMPosition = newSelection == m_frame.selection().selection();
3203     if (selectionDidNotChangeDOMPosition || m_frame.selection().shouldChangeSelection(newSelection))
3204         m_frame.selection().setSelection(newSelection, options);
3205
3206     // Some editing operations change the selection visually without affecting its position within the DOM.
3207     // For example when you press return in the following (the caret is marked by ^):
3208     // <div contentEditable="true"><div>^Hello</div></div>
3209     // WebCore inserts <div><br></div> *before* the current block, which correctly moves the paragraph down but which doesn't
3210     // change the caret's DOM position (["hello", 0]). In these situations the above FrameSelection::setSelection call
3211     // does not call EditorClient::respondToChangedSelection(), which, on the Mac, sends selection change notifications and
3212     // starts a new kill ring sequence, but we want to do these things (matches AppKit).
3213 #if PLATFORM(IOS_FAMILY)
3214     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830>
3215     if (m_ignoreSelectionChanges)
3216         return;
3217 #endif
3218     if (selectionDidNotChangeDOMPosition && client())
3219         client()->respondToChangedSelection(&m_frame);
3220 }
3221
3222 String Editor::selectedText() const
3223 {
3224     TextIteratorBehavior behavior = TextIteratorDefaultBehavior;
3225     if (m_frame.settings().selectionAcrossShadowBoundariesEnabled())
3226         behavior |= TextIteratorTraversesFlatTree;
3227     return selectedText(behavior);
3228 }
3229
3230 String Editor::selectedTextForDataTransfer() const
3231 {
3232     TextIteratorBehavior behavior = TextIteratorEmitsImageAltText;
3233     if (m_frame.settings().selectionAcrossShadowBoundariesEnabled())
3234         behavior |= TextIteratorTraversesFlatTree;
3235     return selectedText(behavior);
3236 }
3237
3238 String Editor::selectedText(TextIteratorBehavior behavior) const
3239 {
3240     // We remove '\0' characters because they are not visibly rendered to the user.
3241     auto& selection = m_frame.selection().selection();
3242     return plainText(selection.start(), selection.end(), behavior).replaceWithLiteral('\0', "");
3243 }
3244
3245 static inline void collapseCaretWidth(IntRect& rect)
3246 {
3247     // FIXME: Width adjustment doesn't work for rotated text.
3248     if (rect.width() == caretWidth)
3249         rect.setWidth(0);
3250     else if (rect.height() == caretWidth)
3251         rect.setHeight(0);
3252 }
3253
3254 IntRect Editor::firstRectForRange(Range* range) const
3255 {
3256     VisiblePosition startVisiblePosition(range->startPosition(), DOWNSTREAM);
3257
3258     if (range->collapsed()) {
3259         // FIXME: Getting caret rect and removing caret width is a very roundabout way to get collapsed range location.
3260         // In particular, width adjustment doesn't work for rotated text.
3261         IntRect startCaretRect = RenderedPosition(startVisiblePosition).absoluteRect();
3262         collapseCaretWidth(startCaretRect);
3263         return startCaretRect;
3264     }
3265
3266     VisiblePosition endVisiblePosition(range->endPosition(), UPSTREAM);
3267
3268     if (inSameLine(startVisiblePosition, endVisiblePosition))
3269         return enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(range));
3270
3271     LayoutUnit extraWidthToEndOfLine;
3272     IntRect startCaretRect = RenderedPosition(startVisiblePosition).absoluteRect(&extraWidthToEndOfLine);
3273     if (startCaretRect == IntRect())
3274         return IntRect();
3275
3276     // When start and end aren't on the same line, we want to go from start to the end of its line.
3277     bool textIsHorizontal = startCaretRect.width() == caretWidth;
3278     return textIsHorizontal ?
3279         IntRect(startCaretRect.x(),
3280             startCaretRect.y(),
3281             startCaretRect.width() + extraWidthToEndOfLine,
3282             startCaretRect.height()) :
3283         IntRect(startCaretRect.x(),
3284             startCaretRect.y(),
3285             startCaretRect.width(),
3286             startCaretRect.height() + extraWidthToEndOfLine);
3287 }
3288
3289 bool Editor::shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity affinity, bool stillSelecting) const
3290 {
3291 #if PLATFORM(IOS_FAMILY)
3292     if (m_frame.selectionChangeCallbacksDisabled())
3293         return true;
3294 #endif
3295     return client() && client()->shouldChangeSelectedRange(oldSelection.toNormalizedRange().get(), newSelection.toNormalizedRange().get(), affinity, stillSelecting);
3296 }
3297
3298 void Editor::computeAndSetTypingStyle(EditingStyle& style, EditAction editingAction)
3299 {
3300     if (style.isEmpty()) {
3301         m_frame.selection().clearTypingStyle();
3302         return;
3303     }
3304
3305     // Calculate the current typing style.
3306     RefPtr<EditingStyle> typingStyle;
3307     if (auto existingTypingStyle = m_frame.selection().typingStyle())
3308         typingStyle = existingTypingStyle->copy();
3309     else
3310         typingStyle = EditingStyle::create();
3311     typingStyle->overrideTypingStyleAt(style, m_frame.selection().selection().visibleStart().deepEquivalent());
3312
3313     // Handle block styles, substracting these from the typing style.
3314     RefPtr<EditingStyle> blockStyle = typingStyle->extractAndRemoveBlockProperties();
3315     if (!blockStyle->isEmpty())
3316         ApplyStyleCommand::create(document(), blockStyle.get(), editingAction)->apply();
3317
3318     // Set the remaining style as the typing style.
3319     m_frame.selection().setTypingStyle(WTFMove(typingStyle));
3320 }
3321
3322 void Editor::computeAndSetTypingStyle(StyleProperties& properties, EditAction editingAction)
3323 {
3324     return computeAndSetTypingStyle(EditingStyle::create(&properties), editingAction);
3325 }
3326
3327 void Editor::textFieldDidBeginEditing(Element* e)
3328 {
3329     if (client())
3330         client()->textFieldDidBeginEditing(e);
3331 }
3332
3333 void Editor::textFieldDidEndEditing(Element* e)
3334 {
3335     dismissCorrectionPanelAsIgnored();
3336     if (client())
3337         client()->textFieldDidEndEditing(e);
3338 }
3339
3340 void Editor::textDidChangeInTextField(Element* e)
3341 {
3342     if (client())
3343         client()->textDidChangeInTextField(e);
3344 }
3345
3346 bool Editor::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke)
3347 {
3348     if (client())
3349         return client()->doTextFieldCommandFromEvent(e, ke);
3350
3351     return false;
3352 }
3353
3354 void Editor::textWillBeDeletedInTextField(Element* input)
3355 {
3356     if (client())
3357         client()->textWillBeDeletedInTextField(input);
3358 }
3359
3360 void Editor::textDidChangeInTextArea(Element* e)
3361 {
3362     if (client())
3363         client()->textDidChangeInTextArea(e);
3364 }
3365
3366 void Editor::applyEditingStyleToBodyElement() const
3367 {
3368     auto collection = document().getElementsByTagName(HTMLNames::bodyTag->localName());
3369     unsigned length = collection->length();
3370     for (unsigned i = 0; i < length; ++i)
3371         applyEditingStyleToElement(collection->item(i));
3372 }
3373
3374 void Editor::applyEditingStyleToElement(Element* element) const
3375 {
3376     ASSERT(!element || is<StyledElement>(*element));
3377     if (!is<StyledElement>(element))
3378         return;
3379
3380     // Mutate using the CSSOM wrapper so we get the same event behavior as a script.
3381     auto& style = downcast<StyledElement>(*element).cssomStyle();
3382     style.setPropertyInternal(CSSPropertyWordWrap, "break-word", false);
3383     style.setPropertyInternal(CSSPropertyWebkitNbspMode, "space", false);
3384     style.setPropertyInternal(CSSPropertyLineBreak, "after-white-space", false);
3385 }
3386
3387 bool Editor::findString(const String& target, FindOptions options)
3388 {
3389     Ref<Frame> protection(m_frame);
3390
3391     VisibleSelection selection = m_frame.selection().selection();
3392
3393     RefPtr<Range> resultRange = rangeOfString(target, selection.firstRange().get(), options);
3394
3395     if (!resultRange)
3396         return false;
3397
3398     m_frame.selection().setSelection(VisibleSelection(*resultRange, DOWNSTREAM));
3399
3400     if (!(options.contains(DoNotRevealSelection)))
3401         m_frame.selection().revealSelection();
3402
3403     return true;
3404 }
3405
3406 RefPtr<Range> Editor::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
3407 {
3408     if (target.isEmpty())
3409         return nullptr;
3410
3411     // Start from an edge of the reference range, if there's a reference range that's not in shadow content. Which edge
3412     // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
3413     RefPtr<Range> searchRange(rangeOfContents(document()));
3414
3415     bool forward = !options.contains(Backwards);
3416     bool startInReferenceRange = referenceRange && options.contains(StartInSelection);
3417     if (referenceRange) {
3418         if (forward)
3419             searchRange->setStart(startInReferenceRange ? referenceRange->startPosition() : referenceRange->endPosition());
3420         else
3421             searchRange->setEnd(startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition());
3422     }
3423
3424     RefPtr<ShadowRoot> shadowTreeRoot = referenceRange ? referenceRange->startContainer().containingShadowRoot() : nullptr;
3425     if (shadowTreeRoot) {
3426         if (forward)
3427             searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());
3428         else
3429             searchRange->setStart(*shadowTreeRoot, 0);
3430     }
3431
3432     RefPtr<Range> resultRange = findPlainText(*searchRange, target, options);
3433     // If we started in the reference range and the found range exactly matches the reference range, find again.
3434     // Build a selection with the found range to remove collapsed whitespace.
3435     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
3436     if (startInReferenceRange && areRangesEqual(VisibleSelection(*resultRange).toNormalizedRange().get(), referenceRange)) {
3437         searchRange = rangeOfContents(document());
3438         if (forward)
3439             searchRange->setStart(referenceRange->endPosition());
3440         else
3441             searchRange->setEnd(referenceRange->startPosition());
3442
3443         if (shadowTreeRoot) {
3444             if (forward)
3445                 searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());
3446             else
3447                 searchRange->setStart(*shadowTreeRoot, 0);
3448         }
3449
3450         resultRange = findPlainText(*searchRange, target, options);
3451     }
3452
3453     // If nothing was found in the shadow tree, search in main content following the shadow tree.
3454     if (resultRange->collapsed() && shadowTreeRoot) {
3455         searchRange = rangeOfContents(document());
3456         if (shadowTreeRoot->shadowHost()) {
3457             if (forward)
3458                 searchRange->setStartAfter(*shadowTreeRoot->shadowHost());
3459             else
3460                 searchRange->setEndBefore(*shadowTreeRoot->shadowHost());
3461         }
3462
3463         resultRange = findPlainText(*searchRange, target, options);
3464     }
3465
3466     // If we didn't find anything and we're wrapping, search again in the entire document (this will
3467     // redundantly re-search the area already searched in some cases).
3468     if (resultRange->collapsed() && options.contains(WrapAround)) {
3469         searchRange = rangeOfContents(document());
3470         resultRange = findPlainText(*searchRange, target, options);
3471         // We used to return false here if we ended up with the same range that we started with
3472         // (e.g., the reference range was already the only instance of this text). But we decided that
3473         // this should be a success case instead, so we'll just fall through in that case.
3474     }
3475
3476     return resultRange->collapsed() ? nullptr : resultRange;
3477 }
3478
3479 static bool isFrameInRange(Frame& frame, Range& range)
3480 {
3481     for (auto* ownerElement = frame.ownerElement(); ownerElement; ownerElement = ownerElement->document().ownerElement()) {
3482         if (&ownerElement->document() == &range.ownerDocument()) {
3483             auto result = range.intersectsNode(*ownerElement);
3484             return !result.hasException() && result.releaseReturnValue();
3485         }
3486     }
3487     return false;
3488 }
3489
3490 unsigned Editor::countMatchesForText(const String& target, Range* range, FindOptions options, unsigned limit, bool markMatches, Vector<RefPtr<Range>>* matches)
3491 {
3492     if (target.isEmpty())
3493         return 0;
3494
3495     RefPtr<Range> searchRange;
3496     if (range) {
3497         if (&range->ownerDocument() == &document())
3498             searchRange = range;
3499         else if (!isFrameInRange(m_frame, *range))
3500             return 0;
3501     }
3502     if (!searchRange)
3503         searchRange = rangeOfContents(document());
3504
3505     Node& originalEndContainer = searchRange->endContainer();
3506     int originalEndOffset = searchRange->endOffset();
3507
3508     unsigned matchCount = 0;
3509     do {
3510         auto resultRange = findPlainText(*searchRange, target, options - Backwards);
3511         if (resultRange->collapsed()) {
3512             if (!resultRange->startContainer().isInShadowTree())
3513                 break;
3514
3515             searchRange->setStartAfter(*resultRange->startContainer().shadowHost());
3516             searchRange->setEnd(originalEndContainer, originalEndOffset);
3517             continue;
3518         }
3519
3520         ++matchCount;
3521         if (matches)
3522             matches->append(resultRange.ptr());
3523         
3524         if (markMatches)
3525             document().markers().addMarker(resultRange, DocumentMarker::TextMatch);
3526
3527         // Stop looking if we hit the specified limit. A limit of 0 means no limit.
3528         if (limit > 0 && matchCount >= limit)
3529             break;
3530
3531         // Set the new start for the search range to be the end of the previous
3532         // result range. There is no need to use a VisiblePosition here,
3533         // since findPlainText will use a TextIterator to go over the visible
3534         // text nodes. 
3535         searchRange->setStart(resultRange->endContainer(), resultRange->endOffset());
3536
3537         Node* shadowTreeRoot = searchRange->shadowRoot();
3538         if (searchRange->collapsed() && shadowTreeRoot)
3539             searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());
3540     } while (true);
3541
3542     return matchCount;
3543 }